* wip
This commit is contained in:
parent
4be1117a02
commit
bc0add9aa0
Binary file not shown.
|
After Width: | Height: | Size: 263 B |
Binary file not shown.
|
After Width: | Height: | Size: 296 B |
Binary file not shown.
|
After Width: | Height: | Size: 1010 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -21,7 +21,10 @@ context.JK.ClientInit = class ClientInit
|
|||
this.watchBroadcast()
|
||||
|
||||
checkBroadcast: () =>
|
||||
broadcastActions.load.triggerPromise()
|
||||
broadcastActions.load.triggerPromise().catch(() ->
|
||||
false
|
||||
)
|
||||
|
||||
|
||||
watchBroadcast: () =>
|
||||
if context.JK.currentUserId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
context.JK ||= {}
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
context.JK.SessionMasterMixDialog = class SessionMasterMixDialog
|
||||
constructor: (@app) ->
|
||||
@rest = context.JK.Rest()
|
||||
@logger = context.JK.logger
|
||||
@screen = null
|
||||
@dialogId = 'session-master-mix-dialog'
|
||||
@dialog = null
|
||||
@closeBtn = null
|
||||
|
||||
initialize:() =>
|
||||
dialogBindings =
|
||||
'beforeShow' : @beforeShow
|
||||
'afterShow' : @afterShow
|
||||
'afterHide' : @afterHide
|
||||
|
||||
|
||||
@dialog = $('[layout-id="' + @dialogId + '"]')
|
||||
@app.bindDialog(@dialogId, dialogBindings)
|
||||
@content = @dialog.find(".dialog-inner")
|
||||
|
||||
beforeShow:() =>
|
||||
@logger.debug("session-master-mix-dlg: beforeShow")
|
||||
context.jamClient.SetMixerMode(MIX_MODES.MASTER)
|
||||
|
||||
afterShow:() =>
|
||||
@logger.debug("session-master-mix-dlg: afterShow")
|
||||
|
||||
afterHide:() =>
|
||||
context.jamClient.SetMixerMode(MIX_MODES.PERSONAL)
|
||||
|
||||
|
||||
|
|
@ -10,4 +10,5 @@
|
|||
//= require ./react-components/stores/SessionOtherTracksStore
|
||||
//= require ./react-components/stores/SessionMediaTracksStore
|
||||
//= require_directory ./react-components/stores
|
||||
//= require_directory ./react-components/mixins
|
||||
//= require_directory ./react-components
|
||||
|
|
@ -4,20 +4,29 @@ MixerActions = @MixerActions
|
|||
|
||||
@SessionBackingTrack = React.createClass({
|
||||
|
||||
mixins: [@MasterPersonalMixersMixin]
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
mixer = @mixer()
|
||||
|
||||
unless mixer?
|
||||
logger.debug("ignoring mute because no media mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.props.mixers.mixer], muting)
|
||||
MixerActions.mute([mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
# today, all mixers are the same for a remote participant; so just grab the 1st
|
||||
mixers = @props.mixers
|
||||
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
mixers = @mixers()
|
||||
muteMixer = mixers.mixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
|
|
@ -65,16 +74,16 @@ MixerActions = @MixerActions
|
|||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
context = window
|
||||
|
||||
@SessionChatMixer= React.createClass({
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
unless @props.mixers.mixer
|
||||
logger.debug("ignoring mute; no mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([@props.mixers.mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
muteMixer = @props.mixers.muteMixer
|
||||
vuMixer = @props.mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
pan = if @props.mixers.mixer? then @props.mixers.mixer.pan else 0
|
||||
|
||||
panStyle = {
|
||||
transform: "rotate(#{pan}deg)"
|
||||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
`<div className="session-track chat-mixer">
|
||||
<div className="disabled-track-overlay" />
|
||||
<div className="session-track-contents">
|
||||
<div className="name">Session Voice Chat Output</div>
|
||||
<div className="track-instrument"><img height="45" src="/assets/content/icon_instrument_voice45.png" width="45" /></div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={this.props.mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -2,12 +2,21 @@ context = window
|
|||
|
||||
@SessionInviteMusiciansBtn = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
||||
@inviteMusiciansUtil = new JK.InviteMusiciansUtil(@app)
|
||||
@inviteMusiciansUtil.initialize(JK.FriendSelectorDialogInstance)
|
||||
|
||||
openInviteDialog : (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
#friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', sessionId);
|
||||
#inviteMusiciansUtil.loadFriends();
|
||||
#$(friendInput).show();
|
||||
friendInput = @inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', context.SessionStore.currentSessionId)
|
||||
@inviteMusiciansUtil.loadFriends()
|
||||
$(friendInput).show()
|
||||
@app.layout.showDialog('select-invites')
|
||||
|
||||
render: () ->
|
||||
`<a className="session-invite-musicians" onClick={this.openInviteDialog}>
|
||||
|
|
|
|||
|
|
@ -4,20 +4,29 @@ MixerActions = @MixerActions
|
|||
|
||||
@SessionJamTrack = React.createClass({
|
||||
|
||||
mixins: [@MasterPersonalMixersMixin]
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
mixer = @mixer()
|
||||
|
||||
unless mixer?
|
||||
logger.debug("ignoring mute because no media mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.props.mixers.mixer], muting)
|
||||
MixerActions.mute([mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
# today, all mixers are the same for a remote participant; so just grab the 1st
|
||||
mixers = @props.mixers
|
||||
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
mixers = @mixers()
|
||||
muteMixer = mixers.mixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
|
|
@ -66,16 +75,16 @@ MixerActions = @MixerActions
|
|||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
context = window
|
||||
|
||||
MixerActions = @MixerActions
|
||||
|
||||
@SessionJamTrackCategory = React.createClass({
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.props.mixers.mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
# today, all mixers are the same for a remote participant; so just grab the 1st
|
||||
mixers = @props.mixers
|
||||
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
componentClasses = classNames({
|
||||
"session-track" : true
|
||||
"jam-track-category" : true
|
||||
})
|
||||
|
||||
pan = mixers.mixer.pan
|
||||
|
||||
panStyle = {
|
||||
transform: "rotate(#{pan}deg)"
|
||||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
`<div className={componentClasses}>
|
||||
<div className="session-track-contents">
|
||||
<div className="jam-track-header">JamTrack:</div>
|
||||
<div className="name">{this.props.jamTrackName}</div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
@SessionMasterCategoryControls = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@SessionMediaTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
mixers = sessionMixers.mixers
|
||||
inputGroupMixers = mixers.getAudioInputCategoryMixer(MIX_MODES.MASTER)
|
||||
chatGroupMixers = mixers.getChatCategoryMixer(MIX_MODES.MASTER)
|
||||
|
||||
@setState({inputGroupMixers: inputGroupMixers, chatGroupMixers: chatGroupMixers})
|
||||
|
||||
render: () ->
|
||||
|
||||
categoryControls = []
|
||||
|
||||
if @state.inputGroupMixers?
|
||||
input =
|
||||
mixers: @state.inputGroupMixers
|
||||
|
||||
categoryControls.push(`<SessionMusicMixer key={input.mixers.mixer.id} {...input} />`)
|
||||
|
||||
if @state.chatGroupMixers?
|
||||
input =
|
||||
mixers: @state.chatGroupMixers
|
||||
|
||||
categoryControls.push(`<SessionChatMixer key={input.mixers.mixer.id} {...input} />`)
|
||||
|
||||
|
||||
`<div className="session-category-controls">
|
||||
<h2>master output</h2>
|
||||
<div className="session-tracks-scroller">
|
||||
{categoryControls}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
|
||||
getInitialState:() ->
|
||||
{inputGroupMixers: null, chatGroupMixers: null}
|
||||
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
SessionActions = @SessionActions
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
EVENTS = context.JK.EVENTS
|
||||
ChannelGroupIds = context.JK.ChannelGroupIds
|
||||
|
||||
@SessionMasterMediaTracks = React.createClass({
|
||||
|
||||
mixins: [@SessionMediaTracksMixin, Reflux.listenTo(@SessionMediaTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
render: () ->
|
||||
|
||||
mediaTracks = []
|
||||
|
||||
if this.state.mediaSummary.mediaOpen
|
||||
|
||||
if this.state.mediaSummary.backingTrackOpen
|
||||
for backingTrack in @state.backingTracks
|
||||
backingTrack.mode = MIX_MODES.MASTER
|
||||
mediaTracks.push(`<SessionBackingTrack key={backingTrack.track.id} {...backingTrack} />`)
|
||||
else if this.state.mediaSummary.jamTrackOpen
|
||||
mediaTracks.push(`<SessionJamTrackCategory key="JamTrackCategory" jamTrackName={this.state.jamTrackName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.MASTER} />`)
|
||||
for jamTrack in @state.jamTracks
|
||||
jamTrack.mode = MIX_MODES.MASTER
|
||||
mediaTracks.push(`<SessionJamTrack key={jamTrack.id} {...jamTrack} />`)
|
||||
else if this.state.mediaSummary.recordingOpen
|
||||
mediaTracks.push(`<SessionRecordedCategory key="RecordedCategory" recordingName={this.state.recordingName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.MASTER} />`)
|
||||
for recordedTrack in @state.recordedTracks
|
||||
recordedTrack.mode = MIX_MODES.MASTER
|
||||
mediaTracks.push(`<SessionRecordedTrack key={recordedTrack.track.id} {...recordedTrack} />`)
|
||||
else if this.state.mediaSummary.metronomeOpen
|
||||
@state.metronome.mode = MIX_MODES.MASTER
|
||||
mediaTracks.push(`<SessionMetronome key={this.state.metronome.id} {...this.state.metronome} />`)
|
||||
|
||||
`<div className="session-media-tracks">
|
||||
<h2>recorded audio</h2>
|
||||
<div className="session-tracks-scroller">
|
||||
{mediaTracks}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
|
||||
getInitialState:() ->
|
||||
{mediaSummary:{mediaOpen: false}, isRecording: false, backingTracks: [], jamTracks: [], recordedTracks: [], metronome: null}
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
@SessionMasterMix = React.createClass({
|
||||
|
||||
render: () ->
|
||||
`<div id="master-tracks">
|
||||
<SessionMasterMyTracks mode={MIX_MODES.MASTER} />
|
||||
<SessionMasterOtherTracks mode={MIX_MODES.MASTER} />
|
||||
<SessionMasterMediaTracks mode={MIX_MODES.MASTER} />
|
||||
<SessionMasterCategoryControls />
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
context = window
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
logger = context.JK.logger
|
||||
|
||||
@SessionMasterMyTracks = React.createClass({
|
||||
|
||||
mixins: [@SessionMyTracksMixin, Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
render: () ->
|
||||
|
||||
content = null
|
||||
tracks = []
|
||||
|
||||
if this.state.tracks.length > 0
|
||||
for track in this.state.tracks
|
||||
track.mode = MIX_MODES.MASTER
|
||||
tracks.push(`<SessionMyTrack key={track.track.client_track_id} {...track} />`)
|
||||
|
||||
if @state.chat
|
||||
@state.chat.mode = @props.mode
|
||||
tracks.push(`<SessionMyChat key="chat" {...this.state.chat} />`)
|
||||
|
||||
else if this.state.session? && this.state.session.inSession()
|
||||
logger.debug("no 'my inputs' for master mix")
|
||||
|
||||
`<div className="session-my-tracks">
|
||||
<h2>my live tracks</h2>
|
||||
<div className="session-tracks-scroller">
|
||||
{content}
|
||||
{tracks}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState:() ->
|
||||
{tracks:[], session: null}
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
})
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
context = window
|
||||
|
||||
MixerActions = @MixerActions
|
||||
|
||||
@SessionMasterOtherTrack = React.createClass({
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
unless @props.mixers.mixer?
|
||||
logger.debug("ignoring mute; no mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([@props.mixers.mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
muteMixer = @props.mixers.muteMixer
|
||||
vuMixer = @props.mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
pan = if @props.mixers.mixer? then @props.mixers.mixer.pan else 0
|
||||
|
||||
panStyle = {
|
||||
transform: "rotate(#{pan}deg)"
|
||||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
# <div className="track-icon-equalizer" />
|
||||
|
||||
`<div className="session-track my-track">
|
||||
<div className="disabled-track-overlay" />
|
||||
<div className="session-track-contents">
|
||||
<div className="name">{this.props.name}</div>
|
||||
<div className="track-avatar"><img src={this.props.photoUrl}/></div>
|
||||
<div className="track-instrument"><img height="45" src={this.props.instrumentIcon} width="45" /></div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={this.props.mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:this.props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:this.props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
# disable hover effects if there is no mixer
|
||||
if nextProps.mixers.mixer?
|
||||
$mute.off("click", false)
|
||||
$pan.off("click", false)
|
||||
else
|
||||
$mute.on("click", false)
|
||||
$pan.on("click", false)
|
||||
})
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
context = window
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
||||
|
||||
@SessionMasterOtherTracks = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@SessionOtherTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
noAudioUsers = mixers.noAudioUsers
|
||||
|
||||
tracks = []
|
||||
|
||||
if session.inSession()
|
||||
|
||||
for participant in session.otherParticipants()
|
||||
|
||||
name = participant.user.name;
|
||||
|
||||
firstTrack = participant.tracks[0]
|
||||
|
||||
photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url)
|
||||
|
||||
for track in participant.tracks
|
||||
|
||||
mixerData = mixers.findMixerForTrack(participant.client_id, track, false, @props.mode)
|
||||
|
||||
instrumentIcon = context.JK.getInstrumentIcon45(firstTrack.instrument_id)
|
||||
|
||||
trackState = {
|
||||
participant: participant,
|
||||
track: track,
|
||||
mixers: mixerData,
|
||||
name: name,
|
||||
instrumentIcon: instrumentIcon,
|
||||
photoUrl: photoUrl,
|
||||
hasMixer: mixerData.mixer? ,
|
||||
noAudio: noAudioUsers[participant.client_id]
|
||||
}
|
||||
|
||||
tracks.push(trackState)
|
||||
# todo: sessionModel.setAudioEstablished
|
||||
|
||||
this.setState(tracks: tracks, session: session)
|
||||
|
||||
render: () ->
|
||||
|
||||
tracks = []
|
||||
|
||||
for track in @state.tracks
|
||||
tracks.push(`<SessionMasterOtherTrack key={track.track.client_track_id} {...track} />`)
|
||||
|
||||
`<div className="session-other-tracks">
|
||||
<h2>other live tracks</h2>
|
||||
<div className="session-tracks-scroller">
|
||||
{tracks}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState:() ->
|
||||
{tracks:[], session: null}
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
})
|
||||
|
|
@ -8,40 +8,26 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
|
||||
@SessionMediaTracks = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@SessionMediaTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
mixins: [@SessionMediaTracksMixin, Reflux.listenTo(@SessionMediaTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
backingTracks = mixers.backingTracks
|
||||
jamTracks = mixers.jamTracks
|
||||
recordedTracks = mixers.recordedTracks
|
||||
metronome = mixers.metronome
|
||||
|
||||
state =
|
||||
isRecording: session.isRecording
|
||||
mediaSummary: mixers.mediaSummary
|
||||
backingTracks: backingTracks
|
||||
jamTracks: jamTracks
|
||||
recordedTracks: recordedTracks
|
||||
metronome: metronome
|
||||
inputsChangedProcessed: (state) ->
|
||||
|
||||
if state.mediaSummary.mediaOpen
|
||||
if !@state.childWindow?
|
||||
logger.debug("OPENING CHILD WINDOW")
|
||||
childWindow = window.open("/popups/media-controls", 'Media Controls', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350')
|
||||
childWindow.PopupProps = state
|
||||
state.childWindow = childWindow
|
||||
else
|
||||
if @state.childWindow?
|
||||
@state.childWindow.DontAutoCloseMedia = true
|
||||
@state.childWindow.close()
|
||||
state.childWindow = null
|
||||
if !state.metronomeFlickerTimeout? # if the metronomeFlickerTimeout is active, we don't consider closing the childWindow
|
||||
@checkCloseWindow()
|
||||
state.childWindow = null
|
||||
|
||||
@setState(state)
|
||||
checkCloseWindow: () ->
|
||||
if @state.childWindow?
|
||||
logger.debug("CLOSING CHILD WINDOW")
|
||||
@state.childWindow.DontAutoCloseMedia = true
|
||||
@state.childWindow.close()
|
||||
|
||||
|
||||
closeAudio: (e) ->
|
||||
|
|
@ -252,16 +238,22 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
</a>`
|
||||
|
||||
|
||||
for backingTrack in @state.backingTracks
|
||||
mediaTracks.push(`<SessionBackingTrack key={backingTrack.track.id} {...backingTrack} />`)
|
||||
|
||||
for jamTrack in @state.jamTracks
|
||||
mediaTracks.push(`<SessionJamTrack key={jamTrack.id} {...jamTrack} />`)
|
||||
|
||||
for recordedTrack in @state.recordedTracks
|
||||
mediaTracks.push(`<SessionRecordedTrack key={recordedTrack.track.id} {...recordedTrack} />`)
|
||||
|
||||
if @state.metronome
|
||||
if this.state.mediaSummary.backingTrackOpen
|
||||
for backingTrack in @state.backingTracks
|
||||
backingTrack.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionBackingTrack key={backingTrack.track.id} {...backingTrack} />`)
|
||||
else if this.state.mediaSummary.jamTrackOpen
|
||||
mediaTracks.push(`<SessionJamTrackCategory key="JamTrackCategory" jamTrackName={this.state.jamTrackName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.PERSONAL} />`)
|
||||
for jamTrack in @state.jamTracks
|
||||
jamTrack.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionJamTrack key={jamTrack.id} {...jamTrack} />`)
|
||||
else if this.state.mediaSummary.recordingOpen
|
||||
mediaTracks.push(`<SessionRecordedCategory key="RecordedCategory" recordingName={this.state.recordingName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.PERSONAL} />`)
|
||||
for recordedTrack in @state.recordedTracks
|
||||
recordedTrack.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionRecordedTrack key={recordedTrack.track.id} {...recordedTrack} />`)
|
||||
else if this.state.mediaSummary.metronomeOpen
|
||||
@state.metronome.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionMetronome key={this.state.metronome.id} {...this.state.metronome} />`)
|
||||
|
||||
contents = closeOptions
|
||||
|
|
@ -311,6 +303,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
# kick off the download JamTrack process
|
||||
@state.downloadJamTrack.init()
|
||||
|
||||
@checkCloseWindow() if !@state.mediaSummary.mediaOpen && !@state.metronomeFlickerTimeout?
|
||||
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ MixerActions = @MixerActions
|
|||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
|
|
@ -76,6 +76,6 @@ MixerActions = @MixerActions
|
|||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ context = window
|
|||
|
||||
@SessionMixerBtn = React.createClass({
|
||||
|
||||
openDialog: (e) ->
|
||||
e.preventDefault()
|
||||
context.JK.app.layout.showDialog('session-master-mix-dialog')
|
||||
|
||||
render: () ->
|
||||
`<a className="session-mixer button-grey left">
|
||||
`<a className="session-mixer button-grey left" onClick={this.openDialog}>
|
||||
<img src="/assets/content/icon_settings_sm.png" align="texttop" height="12" width="12"/>
|
||||
MIXER
|
||||
</a>`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
context = window
|
||||
|
||||
@SessionMusicMixer= React.createClass({
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
unless @props.mixers.mixer
|
||||
logger.debug("ignoring mute; no mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([@props.mixers.mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
muteMixer = @props.mixers.muteMixer
|
||||
vuMixer = @props.mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
pan = if @props.mixers.mixer? then @props.mixers.mixer.pan else 0
|
||||
|
||||
panStyle = {
|
||||
transform: "rotate(#{pan}deg)"
|
||||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
`<div className="session-track music-mixer">
|
||||
<div className="disabled-track-overlay" />
|
||||
<div className="session-track-contents">
|
||||
<div className="name">Session Music Output</div>
|
||||
<div className="track-instrument"><img height="45" src="/assets/content/icon_instrument_voice45.png" width="45" /></div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={this.props.mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
context = window
|
||||
|
||||
MixerActions = @MixerActions
|
||||
|
||||
@SessionMyChat = React.createClass({
|
||||
|
||||
mixins: [@MasterPersonalMixersMixin]
|
||||
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
mixers = @mixers()
|
||||
unless mixers.mixer
|
||||
logger.debug("ignoring mute; no mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([mixers.mixer, mixers.oppositeMixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
mixers = @mixers()
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
|
||||
# <div className="track-icon-equalizer" />
|
||||
|
||||
`<div className="session-track my-track">
|
||||
<div className="disabled-track-overlay" />
|
||||
<div className="session-track-contents">
|
||||
<div className="name">{this.props.name}</div>
|
||||
<div className="track-avatar"><img src={this.props.photoUrl}/></div>
|
||||
<div className="track-instrument"><img height="45" src='/assets/content/icon_instrument_chat45.png' width="45" /></div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
})
|
||||
|
|
@ -70,17 +70,17 @@ MixerActions = @MixerActions
|
|||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:this.props.mixers, mixerFinder: this.props.mixerFinder}
|
||||
{mixers:this.props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:this.props.mixers, mixerFinder: this.props.mixerFinder}
|
||||
{mixers:this.props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
$root = $(this.getDOMNode())
|
||||
|
|
|
|||
|
|
@ -1,51 +1,27 @@
|
|||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
|
||||
@SessionMyTracks = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
tracks = []
|
||||
|
||||
if session.inSession()
|
||||
participant = session.getParticipant(@app.clientId)
|
||||
|
||||
if participant
|
||||
name = participant.user.name;
|
||||
|
||||
for track in participant.tracks
|
||||
# try to find mixer info for this track
|
||||
mixerFinder = [participant.client_id, track, true] # so that other callers can re-find their mixer data
|
||||
mixerData = mixers.findMixerForTrack(participant.client_id, track, true)
|
||||
|
||||
# todo: sessionModel.setAudioEstablished
|
||||
|
||||
instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
|
||||
photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
|
||||
|
||||
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, name: name, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id})
|
||||
|
||||
# TODO: also deal with chat
|
||||
else
|
||||
logger.debug("SessionMyTracks: unable to find participant")
|
||||
|
||||
this.setState(tracks: tracks, session:session)
|
||||
mixins: [@SessionMyTracksMixin, Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
render: () ->
|
||||
|
||||
content = null
|
||||
tracks = []
|
||||
|
||||
if this.state.tracks.length > 0
|
||||
for track in this.state.tracks
|
||||
if @state.tracks.length > 0
|
||||
for track in @state.tracks
|
||||
track.mode = MIX_MODES.PERSONAL
|
||||
tracks.push(`<SessionMyTrack key={track.track.client_track_id} {...track} />`)
|
||||
|
||||
else if this.state.session? && this.state.session.inSession()
|
||||
if @state.chat
|
||||
@state.chat.mode = @props.mode
|
||||
tracks.push(`<SessionMyChat key="chat" {...this.state.chat} />`)
|
||||
|
||||
else if @state.session? && @state.session.inSession()
|
||||
content = `<div className="session-mytracks-notracks">
|
||||
<p className="notice">
|
||||
You have not set up any inputs for your instrument or vocals.
|
||||
|
|
@ -67,7 +43,7 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
|||
</div>`
|
||||
|
||||
getInitialState:() ->
|
||||
{tracks:[], session: null}
|
||||
{tracks:[], session: null, chat:null}
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
|
|
|||
|
|
@ -81,8 +81,7 @@ MixerActions = @MixerActions
|
|||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
mixers = if this.props.tracks.length > 0 then this.props.tracks[0].mixers else {}
|
||||
mixerFinder = if this.props.tracks.length > 0 then this.props.tracks[0].mixerFinder else null
|
||||
{mixers:mixers, mixerFinder: mixerFinder}
|
||||
{mixers:mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
|
||||
|
|
@ -91,8 +90,7 @@ MixerActions = @MixerActions
|
|||
'SessionTrackPanHover',
|
||||
() =>
|
||||
mixers = if this.props.tracks.length > 0 then this.props.tracks[0].mixers else {}
|
||||
mixerFinder = if this.props.tracks.length > 0 then this.props.tracks[0].mixerFinder else null
|
||||
{mixers:mixers, mixerFinder: mixerFinder}
|
||||
{mixers:mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
|||
mixins: [Reflux.listenTo(@SessionOtherTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
noAudioUsers = mixers.noAudioUsers
|
||||
|
|
@ -25,23 +24,31 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
|||
|
||||
for track in participant.tracks
|
||||
# try to find mixer info for this track
|
||||
mixerFinder = [participant.client_id, track, false] # so that other callers can re-find their mixer data
|
||||
mixerFinder = [participant.client_id, track, false] # so that other callers can re-find their mixer data
|
||||
|
||||
mixerData = mixers.findMixerForTrack(participant.client_id, track, false)
|
||||
mixerData = mixers.findMixerForTrack(participant.client_id, track, false, @props.mode)
|
||||
if mixerData.mixer?
|
||||
hasMixer = true
|
||||
|
||||
tracks.push(track: track, mixers: mixerData, mixerFinder: mixerFinder)
|
||||
# todo: sessionModel.setAudioEstablished
|
||||
# todo: sessionModel.setAudioEstablished
|
||||
|
||||
instrumentIcon = context.JK.getInstrumentIcon45(firstTrack.instrument_id)
|
||||
photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url)
|
||||
|
||||
participantState = {participant:participant, tracks: tracks, name: name, instrumentIcon: instrumentIcon, photoUrl: photoUrl, hasMixer: hasMixer, noAudio: noAudioUsers[participant.client_id]}
|
||||
participantState = {
|
||||
participant: participant,
|
||||
tracks: tracks,
|
||||
name: name,
|
||||
instrumentIcon: instrumentIcon,
|
||||
photoUrl: photoUrl,
|
||||
hasMixer: hasMixer,
|
||||
noAudio: noAudioUsers[participant.client_id]
|
||||
}
|
||||
|
||||
participants.push(participantState)
|
||||
|
||||
this.setState(participants:participants, session:session)
|
||||
this.setState(participants: participants, session: session)
|
||||
|
||||
render: () ->
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
context = window
|
||||
|
||||
MixerActions = @MixerActions
|
||||
|
||||
@SessionRecordedCategory = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.props.mixers.mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
# today, all mixers are the same for a remote participant; so just grab the 1st
|
||||
mixers = @props.mixers
|
||||
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
'enabled' : !muteMixer?.mute
|
||||
'muted' : muteMixer?.mute
|
||||
})
|
||||
|
||||
componentClasses = classNames({
|
||||
"session-track" : true
|
||||
"recorded-category" : true
|
||||
})
|
||||
|
||||
pan = mixers.mixer.pan
|
||||
|
||||
panStyle = {
|
||||
transform: "rotate(#{pan}deg)"
|
||||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
`<div className={componentClasses}>
|
||||
<div className="session-track-contents">
|
||||
<div className="name">{this.props.recordingName}</div>
|
||||
<div className="track-controls">
|
||||
<SessionTrackVU orientation="horizontal" lightCount={4} lightWidth={17} lightHeight={3} side="vul" mixers={mixers} />
|
||||
<div className="track-buttons">
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
@ -4,20 +4,29 @@ MixerActions = @MixerActions
|
|||
|
||||
@SessionRecordedTrack = React.createClass({
|
||||
|
||||
mixins: [@MasterPersonalMixersMixin]
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
mixer = @mixer()
|
||||
|
||||
unless mixer?
|
||||
logger.debug("ignoring mute because no media mixer")
|
||||
return
|
||||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.props.mixers.mixer], muting)
|
||||
MixerActions.mute([mixer], muting)
|
||||
|
||||
render: () ->
|
||||
|
||||
# today, all mixers are the same for a remote participant; so just grab the 1st
|
||||
mixers = @props.mixers
|
||||
|
||||
muteMixer = mixers.muteMixer
|
||||
vuMixer = mixers.vuMixer
|
||||
mixers = @mixers()
|
||||
muteMixer = mixers.mixer
|
||||
muteMixerId = muteMixer?.id
|
||||
|
||||
classes = classNames({
|
||||
|
|
@ -57,7 +66,6 @@ MixerActions = @MixerActions
|
|||
|
||||
componentDidMount: () ->
|
||||
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
$pan = $root.find('.track-icon-pan')
|
||||
|
|
@ -66,16 +74,16 @@ MixerActions = @MixerActions
|
|||
$mute,
|
||||
'SessionTrackVolumeHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
context.JK.interactReactBubble(
|
||||
$pan,
|
||||
'SessionTrackPanHover',
|
||||
() =>
|
||||
{mixers:@props.mixers}
|
||||
{mixers:@mixers()}
|
||||
,
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
|
||||
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')})
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
SessionActions = @SessionActions
|
||||
|
||||
|
|
@ -19,9 +20,9 @@ SessionActions = @SessionActions
|
|||
<SessionLeaveBtn />
|
||||
</div>
|
||||
<div className="tracks" id="new-tracks">
|
||||
<SessionMyTracks />
|
||||
<SessionOtherTracks />
|
||||
<SessionMediaTracks />
|
||||
<SessionMyTracks mode={MIX_MODES.PERSONAL} />
|
||||
<SessionOtherTracks mode={MIX_MODES.PERSONAL} />
|
||||
<SessionMediaTracks mode={MIX_MODES.PERSONAL} />
|
||||
<SessionNotifications />
|
||||
</div>
|
||||
</div>`
|
||||
|
|
@ -73,5 +74,5 @@ SessionActions = @SessionActions
|
|||
'beforeDisconnect' : @beforeDisconnect,
|
||||
};
|
||||
|
||||
@app.bindScreen('session2', screenBindings);
|
||||
@app.bindScreen('session', screenBindings);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ MixerActions = @MixerActions
|
|||
inputGroupMixers = mixers.getAudioInputCategoryMixer(MIX_MODES.PERSONAL)
|
||||
chatGroupMixers = mixers.getChatCategoryMixer( MIX_MODES.PERSONAL)
|
||||
|
||||
this.setState({inputGroupMixers: inputGroupMixers, chatGroupMixers: chatGroupMixers})
|
||||
@setState({inputGroupMixers: inputGroupMixers, chatGroupMixers: chatGroupMixers})
|
||||
|
||||
getInitialState: () ->
|
||||
{inputGroupMixers: @props.inputGroupMixers, chatGroupMixers: @props.chatGroupMixers}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,22 @@ logger = context.JK.logger
|
|||
|
||||
getInitialState: () ->
|
||||
{
|
||||
mixers: this.props.mixers,
|
||||
behaviors: this.props.behaviors || {}
|
||||
mixers: @props.mixers,
|
||||
behaviors: @props.behaviors || {}
|
||||
}
|
||||
|
||||
faderChanged: (e, data) ->
|
||||
$target = $(this)
|
||||
groupId = $target.data('groupId')
|
||||
mixerIds = [this.state.mixers.mixer.id]
|
||||
mixers = [@state.mixers.mixer]
|
||||
|
||||
MixerActions.faderChanged(data, mixerIds, groupId)
|
||||
MixerActions.faderChanged(data, mixers, groupId)
|
||||
|
||||
render: () ->
|
||||
mixerId = this.state.mixers?.mixer?.id
|
||||
|
||||
`<div className="track-gain">
|
||||
<div className="fader vertical" data-control="fader" data-fader-id={this.state.mixers.mixer.id} data-orientation="vertical">
|
||||
<div className="fader vertical" data-control="fader" data-fader-id={mixerId} data-orientation="vertical">
|
||||
<div className="handle" data-control="fader-handle">
|
||||
<img src="/assets/content/slider_gain_vertical.png" width="28" height="11"/>
|
||||
</div>
|
||||
|
|
@ -30,20 +32,20 @@ logger = context.JK.logger
|
|||
if !$root.is('.track-gain')
|
||||
logger.error("unknown root node")
|
||||
|
||||
$fader = $root.attr('data-mixer-id', this.state.mixers.mixer.id).data('groupId', this.state.mixers.mixer.groupId).data('mixer', this.state.mixers.mixer).data('opposite-mixer', this.state.mixers.oppositeMixer)
|
||||
$fader = $root.attr('data-mixer-id', @state.mixers.mixer.id).data('groupId', @state.mixers.mixer.groupId).data('mixer', @state.mixers.mixer).data('opposite-mixer', @state.mixers.oppositeMixer)
|
||||
|
||||
if this.state.behaviors.mediaControlsDisabled
|
||||
$fader.data('media-controls-disabled', true).data('media-track-opener', this.state.behaviors.mediaTrackOpener) # this we be applied later to the fader handle $element
|
||||
if @state.behaviors.mediaControlsDisabled
|
||||
$fader.data('media-controls-disabled', true).data('media-track-opener', @state.behaviors.mediaTrackOpener) # this we be applied later to the fader handle $element
|
||||
|
||||
$fader.data('showHelpAboutMediaMixers', this.state.behaviors.showHelpAboutMediaMixers)
|
||||
$fader.data('showHelpAboutMediaMixers', @state.behaviors.showHelpAboutMediaMixers)
|
||||
|
||||
context.JK.FaderHelpers.renderFader2($fader, {faderType: 'vertical'});
|
||||
|
||||
# Initialize gain position
|
||||
MixerActions.initGain(this.state.mixers.mixer)
|
||||
MixerActions.initGain(@state.mixers.mixer)
|
||||
|
||||
# watch for fader change events
|
||||
$fader.on('fader_change', this.faderChanged);
|
||||
$fader.on('fader_change', @faderChanged);
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -12,15 +12,18 @@ logger = context.JK.logger
|
|||
panChanged: (e, data) ->
|
||||
$target = $(this)
|
||||
groupId = $target.data('groupId')
|
||||
mixerIds = [this.state.mixers.mixer.id]
|
||||
mixers = [@state.mixers.mixer]
|
||||
|
||||
MixerActions.panChanged(data, mixerIds, groupId)
|
||||
MixerActions.panChanged(data, mixers, groupId)
|
||||
|
||||
render: () ->
|
||||
|
||||
mixerId = this.state.mixers?.mixer?.id
|
||||
|
||||
`<div className="track-pan">
|
||||
<div className="left-label">Left</div>
|
||||
<div className="right-label">Right</div>
|
||||
<div className="fader horizontal" data-control="fader" data-fader-id={this.state.mixers.mixer.id} data-orientation="horizontal">
|
||||
<div className="fader horizontal" data-control="fader" data-fader-id={mixerId} data-orientation="horizontal">
|
||||
<div className="handle" data-control="fader-handle">
|
||||
<div className="floater"></div>
|
||||
<img src="/assets/content/slider_gain_horiz.png" width="11" height="28"/>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ MixerActions = @MixerActions
|
|||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
mixers = sessionMixers.mixers
|
||||
newMixers = mixers.findMixerForTrack.apply(mixers, this.props.mixerFinder)
|
||||
newMixers = mixers.refreshMixer(@state.mixers)
|
||||
|
||||
this.setState({mixers: newMixers})
|
||||
|
||||
|
|
@ -18,8 +18,6 @@ MixerActions = @MixerActions
|
|||
|
||||
render: () ->
|
||||
|
||||
|
||||
|
||||
`<div className="track-pan-hover">
|
||||
<div className="textual-help">
|
||||
<p>
|
||||
|
|
@ -34,4 +32,12 @@ MixerActions = @MixerActions
|
|||
</div>
|
||||
</div>`
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
$root = jQuery(this.getDOMNode())
|
||||
|
||||
# if the mixers go dead, whack our selves out of existence
|
||||
unless nextState.mixers?
|
||||
$container = $root.closest('.react-holder')
|
||||
$container.data('bt').btOff()
|
||||
return
|
||||
})
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
context = window
|
||||
ptrCount = 0
|
||||
|
||||
@SessionTrackVU = React.createClass({
|
||||
|
||||
|
|
@ -44,28 +45,27 @@ context = window
|
|||
</table>`
|
||||
|
||||
getInitialState: () ->
|
||||
{registered: null}
|
||||
{registered: null, ptr: ptrCount++}
|
||||
|
||||
registerVU: (mixerId) ->
|
||||
registerVU: (mixer) ->
|
||||
|
||||
return if @state.registered? || !mixerId?
|
||||
return if @state.registered? || !mixer?
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
|
||||
context.JK.VuHelpers.registerVU('single', mixerId, @render, @props.orientation == 'horizontal', @props.lightCount, $root.find('td'))
|
||||
context.JK.VuHelpers.registerVU('single', mixer, @state.ptr, @props.orientation == 'horizontal', @props.lightCount, $root.find('td'))
|
||||
|
||||
@setState(registered: {mixerId: mixerId, ptr: @render})
|
||||
@setState(registered: {mixer: mixer, ptr: @state.ptr})
|
||||
|
||||
|
||||
componentWillReceiveProps: (nextProps) ->
|
||||
@registerVU(nextProps.mixers.mixer?.id)
|
||||
@registerVU(nextProps.mixers?.vuMixer)
|
||||
|
||||
componentDidMount: () ->
|
||||
@registerVU(@props.mixers.mixer?.id)
|
||||
@registerVU(@props.mixers?.vuMixer)
|
||||
|
||||
componentWillUnmount: () ->
|
||||
console.log("UNMOUNTING")
|
||||
if @state.registered?
|
||||
context.JK.VuHelpers.unregisterVU(@state.registered.mixerId, @state.registered.ptr)
|
||||
context.JK.VuHelpers.unregisterVU(@state.registered.mixer, @state.registered.ptr)
|
||||
|
||||
})
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
context = window
|
||||
|
||||
ChannelGroupIds = context.JK.ChannelGroupIds
|
||||
MixerActions = @MixerActions
|
||||
|
||||
@SessionTrackVolumeHover = React.createClass({
|
||||
|
||||
btElement: null
|
||||
mixins: [Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged")]
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
mixers = sessionMixers.mixers
|
||||
newMixers = mixers.findMixerForTrack.apply(mixers, this.props.mixerFinder)
|
||||
newMixers = mixers.refreshMixer(@state.mixers)
|
||||
|
||||
this.setState({mixers: newMixers})
|
||||
|
||||
|
|
@ -21,19 +22,27 @@ MixerActions = @MixerActions
|
|||
|
||||
muting = $(e.currentTarget).is('.enabled')
|
||||
|
||||
MixerActions.mute([this.state.mixers.mixer, this.state.mixers.oppositeMixer], muting)
|
||||
if @state.mixers.mixer.group_id == ChannelGroupIds.AudioInputMusicGroup || @state.mixers.mixer.group_id == ChannelGroupIds.AudioInputChatGroup
|
||||
MixerActions.mute([this.state.mixers.mixer, this.state.mixers.oppositeMixer], muting)
|
||||
else
|
||||
MixerActions.mute([this.state.mixers.mixer], muting)
|
||||
|
||||
|
||||
handleMuteCheckbox: (e) ->
|
||||
muting = $(e.target).is(':checked')
|
||||
|
||||
MixerActions.mute([this.state.mixers.mixer, this.state.mixers.oppositeMixer], muting)
|
||||
if @state.mixers.mixer.group_id == ChannelGroupIds.AudioInputMusicGroup || @state.mixers.mixer.group_id == ChannelGroupIds.AudioInputChatGroup
|
||||
MixerActions.mute([this.state.mixers.mixer, this.state.mixers.oppositeMixer], muting)
|
||||
else
|
||||
MixerActions.mute([this.state.mixers.mixer], muting)
|
||||
|
||||
|
||||
render: () ->
|
||||
|
||||
muteMixer = this.state.mixers.muteMixer
|
||||
muteMixer = this.state.mixers?.muteMixer
|
||||
|
||||
muteMixerId = muteMixer?.id
|
||||
volume_left = this.state.mixers.mixer?.volume_left
|
||||
volume_left = this.state.mixers?.mixer?.volume_left
|
||||
|
||||
classes = classNames({
|
||||
'track-icon-mute': true
|
||||
|
|
@ -76,7 +85,7 @@ MixerActions = @MixerActions
|
|||
context.JK.checkbox($checkbox)
|
||||
$checkbox.on('ifChanged', this.handleMuteCheckbox);
|
||||
|
||||
if this.state.mixers.muteMixer.mute
|
||||
if @state.mixers.muteMixer.mute
|
||||
$checkbox.iCheck('check').attr('checked', true)
|
||||
else
|
||||
$checkbox.iCheck('uncheck').attr('checked', false)
|
||||
|
|
@ -84,10 +93,16 @@ MixerActions = @MixerActions
|
|||
componentWillUpdate: (nextProps, nextState) ->
|
||||
$root = jQuery(this.getDOMNode())
|
||||
|
||||
# if the mixers go dead, whack our selves out of existence
|
||||
unless nextState.mixers?
|
||||
$container = $root.closest('.react-holder')
|
||||
$container.data('bt').btOff()
|
||||
return
|
||||
|
||||
# re-initialize icheck
|
||||
$checkbox = $root.find('input')
|
||||
|
||||
if nextState.mixers.muteMixer?.mute
|
||||
if nextState.mixers?.muteMixer?.mute
|
||||
$checkbox.iCheck('check').attr('checked', true)
|
||||
else
|
||||
$checkbox.iCheck('uncheck').attr('checked', false)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
@MixerHelper = class MixerHelper
|
||||
|
||||
constructor: (@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixMode) ->
|
||||
@mixMode = MIX_MODES.PERSONAL # TODO - remove mixMode from MixerHelper? Or at least stop using it in most functions
|
||||
@app = @session.app
|
||||
@mixersByResourceId = {}
|
||||
@mixersByTrackId = {}
|
||||
@allMixers = {}
|
||||
|
|
@ -48,6 +50,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
mixerPair.personal = personalMixer;
|
||||
|
||||
@groupTypes()
|
||||
@chatMixer = @resolveChatMixer()
|
||||
|
||||
groupTypes: () ->
|
||||
localMediaMixers = @mixersForGroupIds(@mediaTrackGroups, MIX_MODES.MASTER)
|
||||
|
|
@ -256,7 +259,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
photoUrl: "/assets/content/icon_recording.png"
|
||||
showLoop: isOpener && !@session.isPlayingRecording()
|
||||
track: serverBackingTrack
|
||||
mixers: {mixer: mixer, oppositeMixer: oppositeMixer, vuMixer: mixer, muteMixer: mixer}
|
||||
mixers: @mediaMixers(mixer, isOpener)
|
||||
|
||||
backingTracks.push(data)
|
||||
|
||||
|
|
@ -320,15 +323,13 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
part = oneOfTheTracks.part
|
||||
part = '' unless name?
|
||||
|
||||
oppositeMixer = @getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL)
|
||||
|
||||
data =
|
||||
name: jamTrackName
|
||||
part: part
|
||||
isOpener: isOpener
|
||||
instrumentIcon: instrumentIcon
|
||||
track: oneOfTheTracks
|
||||
mixers: {mixer: mixer, oppositeMixer: oppositeMixer, vuMixer: mixer, muteMixer: mixer}
|
||||
mixers: @mediaMixers(mixer, isOpener)
|
||||
|
||||
_jamTracks.push(data)
|
||||
|
||||
|
|
@ -341,7 +342,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
serverRecordedTracks = @session.recordedTracks()
|
||||
|
||||
isOpener = @recordingTrackMixers[0].group_id == ChannelGroupIds.MediaTrackGroup;
|
||||
isOpener = @recordingTrackMixers[0].group_id == ChannelGroupIds.MediaTrackGroup
|
||||
|
||||
# using the server's info in conjuction with the client's, draw the recording tracks
|
||||
if serverRecordedTracks
|
||||
|
|
@ -380,16 +381,14 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
instrumentIcon = context.JK.getInstrumentIcon24(oneOfTheTracks.instrument_id)
|
||||
userName = oneOfTheTracks.user.name
|
||||
userName = oneOfTheTracks.user.first_name + ' ' + oneOfTheTracks.user.last_name unless userName?
|
||||
oppositeMixer = @getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL)
|
||||
|
||||
isOpener = mixer.group_id == ChannelGroupIds.MediaTrackGroup
|
||||
data =
|
||||
recordingName: recordingName
|
||||
isOpener: isOpener
|
||||
userName: userName
|
||||
instrumentIcon: instrumentIcon
|
||||
track: oneOfTheTracks
|
||||
mixers: {mixer: mixer, oppositeMixer: oppositeMixer, vuMixer: mixer, muteMixer: mixer}
|
||||
mixers: @mediaMixers(mixer, isOpener)
|
||||
|
||||
recordedTracks.push(data)
|
||||
|
||||
|
|
@ -412,6 +411,56 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
metronome
|
||||
|
||||
resolveChatMixer: () ->
|
||||
masterChatMixers = @mixersForGroupId(ChannelGroupIds.AudioInputChatGroup, MIX_MODES.MASTER);
|
||||
|
||||
return null if masterChatMixers.length == 0
|
||||
|
||||
personalChatMixers = @mixersForGroupId(ChannelGroupIds.AudioInputChatGroup, MIX_MODES.PERSONAL);
|
||||
|
||||
if personalChatMixers.length == 0
|
||||
logger.warn("unable to find personal mixer for voice chat");
|
||||
return null
|
||||
|
||||
|
||||
masterChatMixer = masterChatMixers[0];
|
||||
personalChatMixer = personalChatMixers[0];
|
||||
|
||||
{
|
||||
master: {
|
||||
mixer: masterChatMixer
|
||||
muteMixer: masterChatMixer
|
||||
vuMixer: masterChatMixer
|
||||
oppositeMixer: personalChatMixer
|
||||
}
|
||||
personal: {
|
||||
mixer: personalChatMixer
|
||||
muteMixer: personalChatMixer
|
||||
vuMixer: personalChatMixer
|
||||
oppositeMixer: masterChatMixer
|
||||
}
|
||||
}
|
||||
|
||||
# supply the master mixer of a media track, and this function will harvest out the rest
|
||||
mediaMixers:(masterMixer, isOpener) ->
|
||||
personalMixer = if isOpener then @getMixerByResourceId(masterMixer.rid, MIX_MODES.PERSONAL) else null
|
||||
personalVuMixer = if isOpener then personalMixer else masterMixer
|
||||
{
|
||||
isOpener: isOpener
|
||||
|
||||
master: {
|
||||
mixer: masterMixer
|
||||
muteMixer: masterMixer
|
||||
vuMixer: masterMixer
|
||||
}
|
||||
personal: {
|
||||
mixer: personalMixer
|
||||
muteMixer: personalMixer
|
||||
vuMixer: personalVuMixer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mixersForGroupIds: (groupIds, mixMode) ->
|
||||
foundMixers = []
|
||||
mixers = if mixMode == MIX_MODES.MASTER then @masterMixers else @personalMixers;
|
||||
|
|
@ -434,7 +483,6 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
getMixer: (mixerId, mode) ->
|
||||
mode = @mixMode unless mode?
|
||||
|
||||
@allMixers[(if mode then 'M' else 'P') + mixerId]
|
||||
|
||||
getMixerByTrackId: (trackId, mode) ->
|
||||
|
|
@ -483,15 +531,16 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
return mixerPair.personal
|
||||
|
||||
|
||||
findMixerForTrack: (client_id, track, myTrack) ->
|
||||
findMixerForTrack: (client_id, track, myTrack, mode = MIX_MODES.PERSONAL) ->
|
||||
mixer = null # what is the best mixer for this track/client ID?
|
||||
oppositeMixer = null # what is the corresponding mixer in the opposite mode?
|
||||
vuMixer = null
|
||||
muteMixer = null
|
||||
|
||||
|
||||
if myTrack
|
||||
# when it's your track, look it up by the backend resource ID
|
||||
mixer = @getMixerByTrackId(track.client_track_id, @mixMode)
|
||||
mixer = @getMixerByTrackId(track.client_track_id, mode)
|
||||
vuMixer = mixer
|
||||
muteMixer = mixer
|
||||
|
||||
|
|
@ -501,9 +550,9 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
if mixer
|
||||
# find the matching AudioInputMusicGroup for the opposite mode
|
||||
oppositeMixer = @getMixerByTrackId(track.client_track_id, !@mixMode)
|
||||
oppositeMixer = @getMixerByTrackId(track.client_track_id, !mode)
|
||||
|
||||
if @mixMode == MIX_MODES.PERSONAL
|
||||
if mode == MIX_MODES.PERSONAL
|
||||
muteMixer = oppositeMixer; # make the master mixer the mute mixer
|
||||
|
||||
# sanity checks
|
||||
|
|
@ -514,7 +563,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
else
|
||||
logger.debug("local track is not present: ", track, @allMixers)
|
||||
else
|
||||
switch @mixMode
|
||||
switch mode
|
||||
when MIX_MODES.MASTER
|
||||
|
||||
# when it's a remote track and in master mode, we should find the PeerAudioInputMusicGroup
|
||||
|
|
@ -575,17 +624,10 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
mixer = @getMixer(mixerId, mode)
|
||||
mixer.mute = muting
|
||||
|
||||
faderChanged: (data, mixerIds, groupId) ->
|
||||
# media tracks are the only controls that sometimes set two mixers right now
|
||||
hasMasterAndPersonalControls = mixerIds.length == 2
|
||||
|
||||
for mixerId, i in mixerIds
|
||||
faderChanged: (data, mixers, groupId) ->
|
||||
for mixer in mixers
|
||||
broadcast = !(data.dragging) # If fader is still dragging, don't broadcast
|
||||
mode = undefined
|
||||
if hasMasterAndPersonalControls
|
||||
mode = if i == 0 then MIX_MODES.MASTER else MIX_MODES.PERSONAL
|
||||
|
||||
mixer = @fillTrackVolumeObject(mixerId, mode, broadcast)
|
||||
mixer = @fillTrackVolumeObject(mixer.id, mixer.mode, broadcast)
|
||||
|
||||
@setMixerVolume(mixer, data.percentage)
|
||||
|
||||
|
|
@ -602,12 +644,11 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
context.JK.FaderHelpers.setFaderValue(mixer.id, gainPercent)
|
||||
context.JK.FaderHelpers.showFader(mixer.id)
|
||||
|
||||
panChanged: (data, mixerIds, groupId) ->
|
||||
panChanged: (data, mixers, groupId) ->
|
||||
# media tracks are the only controls that sometimes set two mixers right now
|
||||
for mixerId, i in mixerIds
|
||||
for mixer in mixers
|
||||
broadcast = !(data.dragging) # If fader is still dragging, don't broadcast
|
||||
mode = undefined
|
||||
mixer = @fillTrackVolumeObject(mixerId, mode, broadcast)
|
||||
mixer = @fillTrackVolumeObject(mixer.id, mixer.mode, broadcast)
|
||||
|
||||
@setMixerPan(mixer, data.percentage)
|
||||
|
||||
|
|
@ -626,7 +667,6 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
context.jamClient.SessionSetControlState(mixer.id, mixer.mode);
|
||||
|
||||
loopChanged: (mixer, shouldLoop) ->
|
||||
console.log("mixer, shouldLoop", mixer, shouldLoop)
|
||||
|
||||
@fillTrackVolumeObject(mixer.id, mixer.mode)
|
||||
context.trackVolumeObject.loop = shouldLoop
|
||||
|
|
@ -701,11 +741,8 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
@currentMixerRangeMax = mixer.range_high;
|
||||
mixer
|
||||
|
||||
updateVU: (mixerId, leftValue, leftClipping, rightValue, rightClipping) ->
|
||||
mixer = @getMixer(mixerId, @mixMode)
|
||||
unless mixer
|
||||
# try again, in the opposite mode (awful that this is necessary)
|
||||
mixer = @getMixer(mixerId, !@mixMode)
|
||||
updateVU: (mixerId, mode, leftValue, leftClipping, rightValue, rightClipping) ->
|
||||
mixer = @getMixer(mixerId, mode)
|
||||
|
||||
if mixer
|
||||
context.JK.VuHelpers.updateVU3(mixer, leftValue, leftClipping, rightValue, rightClipping)
|
||||
|
|
@ -733,7 +770,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
if mixers.length == 0
|
||||
logger.warn("could not find mixer with group ID: " + groupId + ', mode:' + mode)
|
||||
return {}
|
||||
return null
|
||||
|
||||
found = null
|
||||
for mixer in mixers
|
||||
|
|
@ -743,7 +780,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
unless found?
|
||||
logger.warn("could not find mixer with categoryId: " + categoryId)
|
||||
return {}
|
||||
return null
|
||||
else
|
||||
{
|
||||
mixer: found,
|
||||
|
|
@ -756,4 +793,34 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
@getGroupMixer(CategoryGroupIds.AudioInputMusic, mode)
|
||||
|
||||
getChatCategoryMixer: (mode) ->
|
||||
@getGroupMixer(CategoryGroupIds.AudioInputChat, mode)
|
||||
@getGroupMixer(CategoryGroupIds.AudioInputChat, mode)
|
||||
|
||||
getMediaCategoryMixer: (mode) ->
|
||||
@getGroupMixer(CategoryGroupIds.MediaTrack, mode)
|
||||
|
||||
getUserMediaCategoryMixer: (mode) ->
|
||||
@getGroupMixer(CategoryGroupIds.UserMedia, mode)
|
||||
|
||||
|
||||
refreshMixer: (mixers) ->
|
||||
return null unless mixers? && mixers.mixer?
|
||||
|
||||
mixer = @getMixer(mixers.mixer.id, mixers.mixer.mode)
|
||||
|
||||
if mixer?
|
||||
oppositeMixer = if mixers.oppositeMixer then @getMixer(mixers.oppositeMixer.id, mixers.oppositeMixer.mode) else null
|
||||
{
|
||||
mixer: mixer
|
||||
vuMixer: @getMixer(mixers.vuMixer.id, mixers.vuMixer.mode)
|
||||
muteMixer: @getMixer(mixers.muteMixer.id, mixers.muteMixer.mode)
|
||||
oppositeMixer: oppositeMixer
|
||||
}
|
||||
else
|
||||
return null
|
||||
|
||||
|
||||
recordingName: () ->
|
||||
@session.recordingName()
|
||||
|
||||
jamTrackName: () ->
|
||||
@session.jamTrackName()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
@MasterPersonalMixersMixin = {
|
||||
|
||||
mixer: () ->
|
||||
if @props.mode == MIX_MODES.MASTER
|
||||
@props.mixers['master'].mixer
|
||||
else
|
||||
@props.mixers['personal'].mixer
|
||||
|
||||
mixers: () ->
|
||||
if @props.mode == MIX_MODES.MASTER
|
||||
@props.mixers['master']
|
||||
else
|
||||
@props.mixers['personal']
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
logger = context.JK.logger
|
||||
|
||||
@SessionMediaTracksMixin = {
|
||||
|
||||
metronomeTrulyGoneCheck: () ->
|
||||
|
||||
logger.debug("metronome is completely gone")
|
||||
@setState({metronomeFlickerTimeout: null})
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
# the backend delete/adds the metronome rapidly when the user hits play. this is custom code to deal with that
|
||||
|
||||
metronomeFlickerTimeout = @state.metronomeFlickerTimeout
|
||||
|
||||
if mixers.metronome?
|
||||
if metronomeFlickerTimeout?
|
||||
logger.debug("canceling metronome flicker timeout because metronome mixer reappeared")
|
||||
clearTimeout(metronomeFlickerTimeout)
|
||||
metronomeFlickerTimeout = null
|
||||
else
|
||||
if @state.metronomeIsShowing
|
||||
logger.debug("setting metronome flicker timeout")
|
||||
clearTimeout(metronomeFlickerTimeout) if metronomeFlickerTimeout?
|
||||
metronomeFlickerTimeout = setTimeout(@metronomeTrulyGoneCheck, 1000)
|
||||
|
||||
metronomeIsShowing = mixers.metronome?
|
||||
|
||||
state =
|
||||
isRecording: session.isRecording
|
||||
mediaSummary: mixers.mediaSummary
|
||||
backingTracks: mixers.backingTracks
|
||||
jamTracks: mixers.jamTracks
|
||||
recordedTracks: mixers.recordedTracks
|
||||
metronome: mixers.metronome
|
||||
mediaCategoryMixer: mixers.getMediaCategoryMixer(@props.mode)
|
||||
recordingName: mixers.recordingName()
|
||||
jamTrackName: mixers.jamTrackName()
|
||||
metronomeIsShowing: metronomeIsShowing
|
||||
metronomeFlickerTimeout: metronomeFlickerTimeout
|
||||
|
||||
@inputsChangedProcessed(state) if @inputsChangedProcessed?
|
||||
|
||||
@setState(state)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
context = window
|
||||
|
||||
@SessionMyTracksMixin = {
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
tracks = []
|
||||
|
||||
if session.inSession()
|
||||
participant = session.getParticipant(@app.clientId)
|
||||
photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
|
||||
|
||||
chatMixer = mixers.chatMixer
|
||||
chat = null
|
||||
if chatMixer
|
||||
chat =
|
||||
mixers: chatMixer
|
||||
mode: @props.mode
|
||||
photoUrl: photoUrl
|
||||
|
||||
|
||||
if participant
|
||||
name = participant.user.name;
|
||||
|
||||
for track in participant.tracks
|
||||
# try to find mixer info for this track
|
||||
mixerFinder = [participant.client_id, track, true] # so that other callers can re-find their mixer data
|
||||
mixerData = mixers.findMixerForTrack(participant.client_id, track, true, @props.mode)
|
||||
|
||||
# todo: sessionModel.setAudioEstablished
|
||||
|
||||
instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
|
||||
|
||||
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, name: name, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id})
|
||||
|
||||
|
||||
else
|
||||
logger.debug("SessionMyTracks: unable to find participant")
|
||||
|
||||
this.setState(tracks: tracks, session:session, chat: chat)
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
context = window
|
||||
|
||||
@SessionOtherTracksMixin = {
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -84,15 +84,16 @@ rest = context.JK.Rest()
|
|||
vuVal = 0.0;
|
||||
if eventName == "vu"
|
||||
mixerId = vuInfo[1];
|
||||
leftValue = vuInfo[2];
|
||||
leftClipping = vuInfo[3];
|
||||
rightValue = vuInfo[4];
|
||||
rightClipping = vuInfo[5];
|
||||
mode = vuInfo[2];
|
||||
leftValue = vuInfo[3];
|
||||
leftClipping = vuInfo[4];
|
||||
rightValue = vuInfo[5];
|
||||
rightClipping = vuInfo[6];
|
||||
# TODO - no guarantee range will be -80 to 20. Get from the
|
||||
# GetControlState for this mixer which returns min/max
|
||||
# value is a DB value from -80 to 20. Convert to float from 0.0-1.0
|
||||
|
||||
@mixers.updateVU(mixerId, (leftValue + 80) / 80, leftClipping, (rightValue + 80) / 80, rightClipping)
|
||||
@mixers.updateVU(mixerId, mode, (leftValue + 80) / 80, leftClipping, (rightValue + 80) / 80, rightClipping)
|
||||
#@mixers.updateVU(mixerId + "_vur", (rightValue + 80) / 80, rightClipping)
|
||||
|
||||
|
||||
|
|
@ -132,14 +133,14 @@ rest = context.JK.Rest()
|
|||
# simulate a state change to cause a UI redraw
|
||||
@issueChange()
|
||||
|
||||
onFaderChanged: (data, mixerIds, groupId) ->
|
||||
onFaderChanged: (data, mixers, groupId) ->
|
||||
|
||||
@mixers.faderChanged(data, mixerIds, groupId)
|
||||
@mixers.faderChanged(data, mixers, groupId)
|
||||
|
||||
@issueChange()
|
||||
|
||||
onPanChanged: (data, mixerIds, groupId) ->
|
||||
@mixers.panChanged(data, mixerIds, groupId)
|
||||
onPanChanged: (data, mixers, groupId) ->
|
||||
@mixers.panChanged(data, mixers, groupId)
|
||||
|
||||
@issueChange()
|
||||
|
||||
|
|
@ -187,13 +188,9 @@ rest = context.JK.Rest()
|
|||
|
||||
onMixersChanged: (type, text) ->
|
||||
|
||||
console.log("MixerStore: onMixersChanged")
|
||||
|
||||
@masterMixers = context.jamClient.SessionGetAllControlState(true);
|
||||
@personalMixers = context.jamClient.SessionGetAllControlState(false);
|
||||
|
||||
console.log("masterMixers", @masterMixers)
|
||||
console.log("personalMixers", @personalMixers)
|
||||
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
|
||||
|
||||
SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo())
|
||||
|
|
@ -201,9 +198,10 @@ rest = context.JK.Rest()
|
|||
@issueChange()
|
||||
|
||||
onMixerModeChanged: (mode) ->
|
||||
|
||||
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, mode)
|
||||
@issueChange()
|
||||
if mode == MIX_MODES.MASTER
|
||||
@app.layout.showDialog('session-master-mix-dialog') unless @app.layout.isDialogShowing('session-master-mix-dialog')
|
||||
else
|
||||
@app.layout.closeDialog('session-master-mix-dialog') if @app.layout.isDialogShowing('session-master-mix-dialog')
|
||||
|
||||
onSyncTracks: () ->
|
||||
logger.debug("MixerStore: onSyncTracks")
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ NotificationActions = @NotificationActions
|
|||
|
||||
@currentSession = sessionData
|
||||
|
||||
console.log("SESSION CHANGED", sessionData)
|
||||
#logger.debug("session changed")
|
||||
|
||||
@issueChange()
|
||||
|
||||
|
|
|
|||
|
|
@ -720,7 +720,7 @@
|
|||
|
||||
// we redirect to the session screen, which handles the REST call to POST /participants.
|
||||
logger.debug("joining session screen: " + sessionId)
|
||||
context.location = '/client#/session2/' + sessionId;
|
||||
context.location = '/client#/session/' + sessionId;
|
||||
};
|
||||
|
||||
if (createSessionSettings.createType == '<%= MusicSession::CREATE_TYPE_START_SCHEDULED%>') {
|
||||
|
|
|
|||
|
|
@ -3286,7 +3286,7 @@
|
|||
'beforeLeave' : beforeLeave,
|
||||
'beforeDisconnect' : beforeDisconnect,
|
||||
};
|
||||
app.bindScreen('session', screenBindings);
|
||||
//app.bindScreen('session', screenBindings);
|
||||
|
||||
$recordingManagerViewer = $('#recording-manager-viewer');
|
||||
$screen = $('#session-screen');
|
||||
|
|
|
|||
|
|
@ -223,7 +223,15 @@
|
|||
reactHovers.btOff();
|
||||
})
|
||||
reactHovers = []
|
||||
var reactElement = null
|
||||
var reactDomNode = null;
|
||||
|
||||
function cleanupReact() {
|
||||
if(reactDomNode) {
|
||||
logger.debug()
|
||||
React.unmountComponentAtNode(reactDomNode)
|
||||
}
|
||||
}
|
||||
function waitForBubbleHover($bubble) {
|
||||
$bubble.hoverIntent({
|
||||
over: function() {
|
||||
|
|
@ -239,7 +247,7 @@
|
|||
|
||||
var timeout = null;
|
||||
|
||||
|
||||
options.postHide = cleanupReact;
|
||||
options.trigger = 'none'
|
||||
options.clickAnywhereToClose = true
|
||||
options.closeWhenOthersOpen = true
|
||||
|
|
@ -248,11 +256,12 @@
|
|||
if(!reactElementName) {
|
||||
throw "unknown react element" + reactElementName
|
||||
}
|
||||
var element = React.createElement(reactElement, reactPropsCallback());
|
||||
|
||||
reactElement= React.createElement(reactElement, reactPropsCallback());
|
||||
var $container = $(container)
|
||||
|
||||
React.render(element, $container.find('.react-holder').get(0))
|
||||
reactDomNode = $container.find('.react-holder').get(0)
|
||||
$(reactDomNode).data('bt', $element)
|
||||
console.log("reactDomNode", reactDomNode)
|
||||
React.render(reactElement, reactDomNode)
|
||||
}
|
||||
options.postShow = function(container) {
|
||||
|
||||
|
|
|
|||
|
|
@ -97,14 +97,20 @@
|
|||
|
||||
},
|
||||
|
||||
createQualifiedId: function(mixer) {
|
||||
return (mixer.mode ? 'M' : 'P') + mixer.id
|
||||
},
|
||||
|
||||
// type can be 'single' or 'double', meaning how the VU is represented (one set of lights, two)
|
||||
// mixerId is the ID of the mixer
|
||||
// and someFunction is used to make the registration (equality check).
|
||||
registerVU: function(type, mixerId, someFunction, horizontal, lightCount, leftLights, rightLights) {
|
||||
var registrations = this.registeredMixers[mixerId]
|
||||
registerVU: function(type, mixer, someFunction, horizontal, lightCount, leftLights, rightLights) {
|
||||
|
||||
var fqId = this.createQualifiedId(mixer)
|
||||
var registrations = this.registeredMixers[fqId]
|
||||
if (!registrations) {
|
||||
registrations = []
|
||||
this.registeredMixers[mixerId] = registrations
|
||||
this.registeredMixers[fqId] = registrations
|
||||
}
|
||||
|
||||
if(type == 'single') {
|
||||
|
|
@ -117,22 +123,26 @@
|
|||
|
||||
},
|
||||
|
||||
unregisterVU: function(mixerId, someFunction) {
|
||||
var registrations = this.registeredMixers[mixerId]
|
||||
unregisterVU: function(mixer, someFunction) {
|
||||
var fqId = this.createQualifiedId(mixer)
|
||||
var registrations = this.registeredMixers[fqId]
|
||||
if (!registrations || registrations.length == 0) {
|
||||
logger.debug("no registration found for: " + type + ":" + mixerId)
|
||||
logger.debug("no registration found for:" + fqId, registrations, this.registeredMixers)
|
||||
return
|
||||
}
|
||||
else {
|
||||
logger.debug("unregistering " + fqId + ", " + registrations.length)
|
||||
}
|
||||
|
||||
var origLength = registrations.length
|
||||
registrations = registrations.filter(function(element) {
|
||||
someFunction !== element.ptr
|
||||
return someFunction !== element.ptr
|
||||
})
|
||||
|
||||
this.registeredMixers[mixerId] = registrations
|
||||
this.registeredMixers[fqId] = registrations
|
||||
|
||||
if(origLength == registrations.length) {
|
||||
logger.warn("did not find anything to unregister for: " + type + ':' + mixerId)
|
||||
logger.warn("did not find anything to unregister for: " + fqId)
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -169,7 +179,9 @@
|
|||
// sentMixerId ends with vul or vur
|
||||
updateVU3: function(mixer, leftValue, leftClipping, rightValue, rightClipping) {
|
||||
|
||||
var registrations = this.registeredMixers[mixer.id]
|
||||
var fqId = this.createQualifiedId(mixer)
|
||||
|
||||
var registrations = this.registeredMixers[fqId]
|
||||
if (registrations) {
|
||||
var j;
|
||||
for(j = 0; j < registrations.length; j++) {
|
||||
|
|
@ -196,53 +208,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a selector representing a container for a VU meter and
|
||||
* a value between 0.0 and 1.0, light the appropriate lights.
|
||||
*/
|
||||
updateVU2: function (side, mixer, value) {
|
||||
// There are 13 VU lights. Figure out how many to
|
||||
// light based on the incoming value.
|
||||
|
||||
var $selector = $('.' + side + '-' + mixer.id)
|
||||
|
||||
$selector.each(function() {
|
||||
var $table = $(this)
|
||||
var horizontal = $table.is('.horizontal')
|
||||
|
||||
var lightCount = Number($table.attr('data-light-count'))
|
||||
|
||||
var i = 0;
|
||||
var state = 'on';
|
||||
var lights = Math.round(value * lightCount);
|
||||
var redSwitch = Math.round(lightCount * 0.6666667);
|
||||
|
||||
var $light = null;
|
||||
var colorClass = 'vu-green-';
|
||||
var thisLightSelector = null;
|
||||
|
||||
// Remove all light classes from all lights
|
||||
var allLightsSelector = $table.find('td');
|
||||
$(allLightsSelector).removeClass('vu-green-off vu-green-on vu-red-off vu-red-on');
|
||||
|
||||
// Set the lights
|
||||
for (i = 0; i < lightCount; i++) {
|
||||
colorClass = 'vu-green-';
|
||||
state = 'on';
|
||||
if (i >= redSwitch) {
|
||||
colorClass = 'vu-red-';
|
||||
}
|
||||
if (i >= lights) {
|
||||
state = 'off';
|
||||
}
|
||||
|
||||
var lightIndex = horizontal ? i : lightCount - i - 1;
|
||||
allLightsSelector.eq(lightIndex).addClass(colorClass + state);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
.jam-track-get-ready, .media-seeking {
|
||||
display:none;
|
||||
position:absolute;
|
||||
top:-29px;
|
||||
top:20px;
|
||||
margin-left:-50px;
|
||||
width:100px;
|
||||
vertical-align:middle;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
position: absolute;
|
||||
top: 90px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
@include border_box_sizing;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
|
@ -92,301 +92,6 @@
|
|||
margin-top:20px;
|
||||
}
|
||||
|
||||
.session-track {
|
||||
float:left;
|
||||
margin: 10px 0;
|
||||
color: $ColorTextTypical;
|
||||
background-color: #242323;
|
||||
border-radius: 6px;
|
||||
min-height: 76px;
|
||||
max-width: 210px;
|
||||
position:relative;
|
||||
@include border_box_sizing;
|
||||
|
||||
.session-track-contents {
|
||||
padding: 6px 6px 6px 10px;
|
||||
}
|
||||
.disabled-track-overlay {
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
background-color:#555;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
&.no-mixer, &.no-audio {
|
||||
.disabled-track-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity:0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// media overrides
|
||||
&.backing-track, &.recorded-track, &.jam-track, &.metronome {
|
||||
width:210px;
|
||||
table.vu {
|
||||
float: right;
|
||||
margin-top: 30px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.track-controls {
|
||||
float:right;
|
||||
}
|
||||
.track-buttons {
|
||||
float:right;
|
||||
}
|
||||
.track-icon-pan {
|
||||
float:right;
|
||||
margin-right:20px;
|
||||
}
|
||||
.track-icon-mute{
|
||||
float:right;
|
||||
}
|
||||
}
|
||||
|
||||
&.metronome {
|
||||
.track-instrument {
|
||||
float:left;
|
||||
margin-left:0;
|
||||
margin-right: 8px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
.track-controls {
|
||||
margin-left:0;
|
||||
}
|
||||
}
|
||||
|
||||
&.recorded-track, &.jam-track {
|
||||
height:56px;
|
||||
min-height:56px;
|
||||
.track-buttons {
|
||||
margin-top:2px;
|
||||
}
|
||||
.track-controls {
|
||||
margin-left:0;
|
||||
}
|
||||
table.vu {
|
||||
margin-top:10px;
|
||||
}
|
||||
.track-instrument {
|
||||
float: left;
|
||||
margin: -2px 7px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.react-holder {
|
||||
&.SessionTrackVolumeHover, &.SessionSelfVolumeHover {
|
||||
height:331px;
|
||||
width:235px;
|
||||
|
||||
.session-track {
|
||||
float:left;
|
||||
background-color: #242323;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
height: 300px;
|
||||
margin-right: 14px;
|
||||
position: relative;
|
||||
width: 70px;
|
||||
margin-top:19px;
|
||||
margin-left:24px;
|
||||
}
|
||||
|
||||
.track-icon-mute {
|
||||
float:none;
|
||||
position: absolute;
|
||||
top: 246px;
|
||||
left: 29px;
|
||||
}
|
||||
|
||||
.track-gain {
|
||||
position:absolute;
|
||||
width:28px;
|
||||
height:209px;
|
||||
top:32px;
|
||||
left:23px;
|
||||
}
|
||||
|
||||
.fader {
|
||||
height:209px;
|
||||
}
|
||||
|
||||
.handle {
|
||||
bottom:0%;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
float:left;
|
||||
width:100px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size:12px;
|
||||
padding:0;
|
||||
margin:16px 0 0;
|
||||
line-height:125%;
|
||||
|
||||
&:nth-child(1) {
|
||||
margin-top:19px;
|
||||
}
|
||||
}
|
||||
|
||||
.icheckbox_minimal {
|
||||
position:absolute;
|
||||
top: 271px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
input {
|
||||
position:absolute;
|
||||
top: 271px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
top:273px;
|
||||
left:34px
|
||||
}
|
||||
}
|
||||
|
||||
#self-volume-hover {
|
||||
h3 {
|
||||
font-size:16px;
|
||||
font-weight:bold;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.monitor-mixer {
|
||||
float:left;
|
||||
width:235px;
|
||||
@include border_box_sizing;
|
||||
padding: 15px 0 15px 0;
|
||||
|
||||
h3 {
|
||||
margin-left:36px;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
border-right:1px solid $ColorTextTypical;
|
||||
float:right;
|
||||
padding-right:25px !important;
|
||||
|
||||
p:nth-child(1) {
|
||||
margin-top:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-mixer {
|
||||
float:left;
|
||||
width:235px;
|
||||
@include border-box-sizing;
|
||||
padding: 15px 0 15px 0;
|
||||
|
||||
h3 {
|
||||
margin-left:41px;
|
||||
}
|
||||
}
|
||||
|
||||
.mixer-holder {
|
||||
|
||||
.session-track {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
margin-top:0;
|
||||
padding-right:10px;
|
||||
|
||||
p:nth-child(1) {
|
||||
margin-top:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
&.SessionTrackVolumeHover {
|
||||
|
||||
}
|
||||
|
||||
&.SessionSelfVolumeHover {
|
||||
width:470px ! important;
|
||||
height:360px ! important;
|
||||
}
|
||||
|
||||
&.SessionTrackPanHover {
|
||||
width:331px;
|
||||
height:197px;
|
||||
padding:15px;
|
||||
@include border_box_sizing;
|
||||
|
||||
.session-pan {
|
||||
.textual-help {
|
||||
float:left;
|
||||
width:100px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size:12px;
|
||||
padding:0;
|
||||
line-height:125%;
|
||||
}
|
||||
.track-pan {
|
||||
background-color: #242323;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
margin-top:15px;
|
||||
}
|
||||
.fader {
|
||||
position:absolute;
|
||||
width:205px;
|
||||
height:24px;
|
||||
top:34px;
|
||||
left:44px;
|
||||
background-image: url('/assets/content/bkg_slider_gain_horiz_24.png');
|
||||
}
|
||||
.handle {
|
||||
display:none;
|
||||
|
||||
img {
|
||||
position:absolute;
|
||||
left:-5px;
|
||||
}
|
||||
}
|
||||
.left-label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
left:13px;
|
||||
top:40px;
|
||||
}
|
||||
.right-label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
right:12px;
|
||||
top:40px;
|
||||
}
|
||||
.floater {
|
||||
width:20px;
|
||||
text-align:center;
|
||||
top:-22px;
|
||||
left:-8px;
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.when-empty {
|
||||
margin-top:20px;
|
||||
|
|
@ -395,109 +100,6 @@
|
|||
overflow:hidden;
|
||||
}
|
||||
|
||||
.session-track {
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
margin-bottom: 6px;
|
||||
@include labelFont;
|
||||
}
|
||||
|
||||
.track-avatar {
|
||||
float: left;
|
||||
padding: 1px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background-color: #ed3618;
|
||||
-webkit-border-radius: 22px;
|
||||
-moz-border-radius: 22px;
|
||||
border-radius: 22px;
|
||||
|
||||
img {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
-webkit-border-radius: 22px;
|
||||
-moz-border-radius: 22px;
|
||||
border-radius: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.track-instrument {
|
||||
float: left;
|
||||
padding: 1px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
table.vu {
|
||||
float: left;
|
||||
|
||||
td {
|
||||
border: 3px solid #242323;
|
||||
}
|
||||
}
|
||||
|
||||
.track-controls {
|
||||
margin-top: 2px;
|
||||
margin-left: 10px;
|
||||
float:left
|
||||
}
|
||||
|
||||
.track-buttons {
|
||||
margin-top:22px;
|
||||
padding:0 0 0 3px;
|
||||
}
|
||||
|
||||
.track-icon-mute {
|
||||
float:left;
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
}
|
||||
|
||||
.track-icon-pan {
|
||||
float:left;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image:url('/assets/content/icon_pan.png');
|
||||
background-repeat:no-repeat;
|
||||
text-align: center;
|
||||
margin-left:10px;
|
||||
//-webkit-transform: rotate(7deg); /* Chrome, Safari, Opera */
|
||||
//transform: rotate(7deg);
|
||||
}
|
||||
|
||||
.track-icon-equalizer {
|
||||
float:left;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image:url('/assets/content/icon_equalizer.png');
|
||||
background-repeat:no-repeat;
|
||||
text-align: center;
|
||||
margin-left:7px;
|
||||
}
|
||||
|
||||
.session-track-list-enter {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.session-track-list-leave {
|
||||
opacity:1;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.session-track-settings {
|
||||
height:20px;
|
||||
cursor:pointer;
|
||||
|
|
@ -607,4 +209,23 @@
|
|||
@include border_box_sizing;
|
||||
padding:6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.session-track-list-enter {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.session-track-list-leave {
|
||||
opacity:1;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,393 @@
|
|||
@import "client/common";
|
||||
|
||||
.session-track {
|
||||
float:left;
|
||||
margin: 10px 0;
|
||||
color: $ColorTextTypical;
|
||||
background-color: #242323;
|
||||
border-radius: 6px;
|
||||
min-height: 76px;
|
||||
max-width: 210px;
|
||||
position:relative;
|
||||
@include border_box_sizing;
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
margin-bottom: 6px;
|
||||
@include labelFont;
|
||||
}
|
||||
|
||||
.track-avatar {
|
||||
float: left;
|
||||
padding: 1px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background-color: #ed3618;
|
||||
-webkit-border-radius: 22px;
|
||||
-moz-border-radius: 22px;
|
||||
border-radius: 22px;
|
||||
|
||||
img {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
-webkit-border-radius: 22px;
|
||||
-moz-border-radius: 22px;
|
||||
border-radius: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.track-instrument {
|
||||
float: left;
|
||||
padding: 1px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
table.vu {
|
||||
float: left;
|
||||
|
||||
td {
|
||||
border: 3px solid #242323;
|
||||
}
|
||||
}
|
||||
|
||||
.session-track-contents {
|
||||
padding: 6px 6px 6px 10px;
|
||||
}
|
||||
.disabled-track-overlay {
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
background-color:#555;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
&.no-mixer, &.no-audio {
|
||||
.disabled-track-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity:0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.track-controls {
|
||||
margin-top: 2px;
|
||||
margin-left: 10px;
|
||||
float:left
|
||||
}
|
||||
|
||||
.track-buttons {
|
||||
margin-top:22px;
|
||||
padding:0 0 0 3px;
|
||||
}
|
||||
|
||||
.track-icon-mute {
|
||||
float:left;
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
}
|
||||
|
||||
.track-icon-pan {
|
||||
float:left;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image:url('/assets/content/icon_pan.png');
|
||||
background-repeat:no-repeat;
|
||||
text-align: center;
|
||||
margin-left:10px;
|
||||
//-webkit-transform: rotate(7deg); /* Chrome, Safari, Opera */
|
||||
//transform: rotate(7deg);
|
||||
}
|
||||
|
||||
.track-icon-equalizer {
|
||||
float:left;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image:url('/assets/content/icon_equalizer.png');
|
||||
background-repeat:no-repeat;
|
||||
text-align: center;
|
||||
margin-left:7px;
|
||||
}
|
||||
|
||||
|
||||
// media overrides
|
||||
&.backing-track, &.recorded-track, &.jam-track, &.metronome, &.recorded-category, &.jam-track-category {
|
||||
width:210px;
|
||||
table.vu {
|
||||
float: right;
|
||||
margin-top: 30px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.track-controls {
|
||||
float:right;
|
||||
}
|
||||
.track-buttons {
|
||||
float:right;
|
||||
}
|
||||
.track-icon-pan {
|
||||
float:right;
|
||||
margin-right:20px;
|
||||
}
|
||||
.track-icon-mute{
|
||||
float:right;
|
||||
}
|
||||
}
|
||||
|
||||
&.metronome {
|
||||
.track-instrument {
|
||||
float:left;
|
||||
margin-left:0;
|
||||
margin-right: 8px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
.track-controls {
|
||||
margin-left:0;
|
||||
}
|
||||
}
|
||||
|
||||
&.recorded-track, &.jam-track, &.recorded-category, &.jam-track-category {
|
||||
height:56px;
|
||||
min-height:56px;
|
||||
.track-buttons {
|
||||
margin-top:2px;
|
||||
}
|
||||
.track-controls {
|
||||
margin-left:0;
|
||||
}
|
||||
table.vu {
|
||||
margin-top:10px;
|
||||
}
|
||||
.track-instrument {
|
||||
float: left;
|
||||
margin: -2px 7px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.recorded-category, &.jam-track-category {
|
||||
height:auto !important;
|
||||
}
|
||||
|
||||
&.jam-track-category {
|
||||
.jam-track-header {
|
||||
position:absolute;
|
||||
@include labelFont;
|
||||
|
||||
}
|
||||
.name {
|
||||
width:auto;
|
||||
margin-left:60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-holder {
|
||||
&.SessionTrackVolumeHover, &.SessionSelfVolumeHover {
|
||||
height:331px;
|
||||
width:235px;
|
||||
|
||||
.session-track {
|
||||
float:left;
|
||||
background-color: #242323;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
height: 300px;
|
||||
margin-right: 14px;
|
||||
position: relative;
|
||||
width: 70px;
|
||||
margin-top:19px;
|
||||
margin-left:24px;
|
||||
}
|
||||
|
||||
.track-icon-mute {
|
||||
float:none;
|
||||
position: absolute;
|
||||
top: 246px;
|
||||
left: 29px;
|
||||
}
|
||||
|
||||
.track-gain {
|
||||
position:absolute;
|
||||
width:28px;
|
||||
height:209px;
|
||||
top:32px;
|
||||
left:23px;
|
||||
}
|
||||
|
||||
.fader {
|
||||
height:209px;
|
||||
}
|
||||
|
||||
.handle {
|
||||
bottom:0%;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
float:left;
|
||||
width:100px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size:12px !important;
|
||||
padding:0;
|
||||
margin:16px 0 0 !important;
|
||||
line-height:125% !important;
|
||||
&:nth-child(1) {
|
||||
margin-top: 19px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.icheckbox_minimal {
|
||||
position:absolute;
|
||||
top: 271px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
input {
|
||||
position:absolute;
|
||||
top: 271px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
top:273px;
|
||||
left:34px
|
||||
}
|
||||
}
|
||||
|
||||
#self-volume-hover {
|
||||
h3 {
|
||||
font-size:16px;
|
||||
font-weight:bold;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.monitor-mixer {
|
||||
float:left;
|
||||
width:235px;
|
||||
@include border_box_sizing;
|
||||
padding: 15px 0 15px 0;
|
||||
|
||||
h3 {
|
||||
margin-left:36px;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
border-right:1px solid $ColorTextTypical;
|
||||
float:right;
|
||||
padding-right:25px !important;
|
||||
|
||||
p:nth-child(1) {
|
||||
margin-top:0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-mixer {
|
||||
float:left;
|
||||
width:235px;
|
||||
@include border-box-sizing;
|
||||
padding: 15px 0 15px 0;
|
||||
|
||||
h3 {
|
||||
margin-left:41px;
|
||||
}
|
||||
}
|
||||
|
||||
.mixer-holder {
|
||||
|
||||
.session-track {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
.textual-help {
|
||||
margin-top:0;
|
||||
padding-right:10px;
|
||||
|
||||
p:nth-child(1) {
|
||||
margin-top:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
&.SessionTrackVolumeHover {
|
||||
|
||||
}
|
||||
|
||||
&.SessionSelfVolumeHover {
|
||||
width:470px ! important;
|
||||
height:360px ! important;
|
||||
}
|
||||
|
||||
&.SessionTrackPanHover {
|
||||
width:331px;
|
||||
height:197px;
|
||||
padding:15px;
|
||||
@include border_box_sizing;
|
||||
|
||||
.session-pan {
|
||||
.textual-help {
|
||||
float:left;
|
||||
width:100px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size:12px !important;
|
||||
padding:0 !important;
|
||||
line-height:125% !important;
|
||||
margin:0 !important;
|
||||
}
|
||||
.track-pan {
|
||||
background-color: #242323;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
margin-top:15px;
|
||||
}
|
||||
.fader {
|
||||
position:absolute;
|
||||
width:205px;
|
||||
height:24px;
|
||||
top:34px;
|
||||
left:44px;
|
||||
background-image: url('/assets/content/bkg_slider_gain_horiz_24.png');
|
||||
}
|
||||
.handle {
|
||||
display:none;
|
||||
|
||||
img {
|
||||
position:absolute;
|
||||
left:-5px;
|
||||
}
|
||||
}
|
||||
.left-label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
left:13px;
|
||||
top:40px;
|
||||
}
|
||||
.right-label {
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
right:12px;
|
||||
top:40px;
|
||||
}
|
||||
.floater {
|
||||
width:20px;
|
||||
text-align:center;
|
||||
top:-22px;
|
||||
left:-8px;
|
||||
@include labelFont;
|
||||
position:absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@import "client/common";
|
||||
|
||||
[layout-id="session"] {
|
||||
[layout-id="session_old"] {
|
||||
|
||||
.resync {
|
||||
margin-left:15px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#invite-musician-friends-dialog {
|
||||
width:450px;
|
||||
|
||||
p.instructions {
|
||||
margin-bottom:30px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#btn-cancel-invites {
|
||||
|
||||
}
|
||||
#btn-save-invites {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
@import "client/common";
|
||||
|
||||
#session-master-mix-dialog {
|
||||
width:1100px;
|
||||
height:466px;
|
||||
|
||||
#master-tracks {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
top: 120px;
|
||||
width: 100%;
|
||||
padding-right: 20px;
|
||||
@include border_box_sizing;
|
||||
}
|
||||
.dialog-inner {
|
||||
padding: 10px 20px;
|
||||
width:100%;
|
||||
|
||||
p.notice {
|
||||
width:800px;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size:24px;
|
||||
}
|
||||
}
|
||||
|
||||
.session-my-tracks, .session-other-tracks, .session-media-tracks, .session-category-controls {
|
||||
@include border_box_sizing;
|
||||
float: left;
|
||||
width: 25%;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
margin-bottom: 15px;
|
||||
color:$ColorTextTypical;
|
||||
overflow:hidden;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.session-tracks-scroller {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
|
||||
padding: 0 15px 0 0;
|
||||
@include border_box_sizing;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom:0;
|
||||
position:absolute;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position:absolute;
|
||||
margin:0 0 0 -30px;
|
||||
bottom:10px;
|
||||
left: 50%;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,23 @@
|
|||
<!-- Session Update Invite Musicians Dialog -->
|
||||
<div class="dialog invitemusicians-overlay" layout="dialog" layout-id="select-invites" style="min-height:180px;">
|
||||
<div id="invite-musician-friends-dialog" class="dialog invitemusicians-overlay" layout="dialog" layout-id="select-invites" style="min-height:180px;">
|
||||
<div class="content-head">
|
||||
<%= image_tag "content/icon_email.png", {:height => 21, :width => 22, :class => 'content-icon'} %>
|
||||
<h1>invite musicians</h1>
|
||||
</div>
|
||||
<div class="dialog-inner">
|
||||
<p class="instructions">
|
||||
Start typing a name, or click the Choose Friends button to invite your JamKazam friends to join your session.
|
||||
</p>
|
||||
<div class="invitemusicians-inner" id="update-session-invite-musicians">
|
||||
</div>
|
||||
<br clear="all" />
|
||||
<div class="right">
|
||||
<a id="btn-save-invites" layout-action="close" class="button-orange">INVITE</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a id="btn-cancel-invites" layout-action="close" class="button-grey">CANCEL</a>
|
||||
<div class="actions">
|
||||
<a id="btn-cancel-invites" layout-action="close" class="button-grey">CANCEL</a>
|
||||
<a id="btn-save-invites" layout-action="close" class="button-orange">INVITE</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- invite musician friend selector template -->
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#session-screen.screen.secondary[layout="screen" layout-id="session" layout-arg="id"]
|
||||
#session-screen.screen.secondary[layout="screen" layout-id="session_old" layout-arg="id"]
|
||||
.content-head
|
||||
.content-icon
|
||||
= image_tag "shared/icon_session.png", {:height => 19, :width => 19}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#session-screen2.screen.secondary[layout="screen" layout-id="session2" layout-arg="id"]
|
||||
#session-screen2.screen.top-parent.secondary[layout="screen" layout-id="session" layout-arg="id"]
|
||||
.content-head
|
||||
.content-icon
|
||||
= image_tag "shared/icon_session.png", {:height => 19, :width => 19}
|
||||
|
|
|
|||
|
|
@ -329,6 +329,9 @@
|
|||
var singlePlayerProfileGuardDialog = new JK.SinglePlayerProfileGuardDialog(JK.app);
|
||||
singlePlayerProfileGuardDialog.initialize();
|
||||
|
||||
var sessionMasterMixDialog = new JK.SessionMasterMixDialog(JK.app);
|
||||
sessionMasterMixDialog.initialize();
|
||||
|
||||
var signinDialog = new JK.SigninDialog(JK.app);
|
||||
signinDialog.initialize();
|
||||
JK.SigninPage(); // initialize signin helper
|
||||
|
|
|
|||
|
|
@ -37,4 +37,5 @@
|
|||
= render 'dialogs/openBackingTrackDialog'
|
||||
= render 'dialogs/loginRequiredDialog'
|
||||
= render 'dialogs/jamtrackPaymentHistoryDialog'
|
||||
= render 'dialogs/singlePlayerProfileGuard'
|
||||
= render 'dialogs/singlePlayerProfileGuard'
|
||||
= render 'dialogs/sessionMasterMixDialog'
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='session-master-mix-dialog' id='session-master-mix-dialog'
|
||||
.content-head
|
||||
= image_tag "shared/icon_session.png", {:height => 19, :width => 19, :class => 'content-icon'}
|
||||
h1 session master mix
|
||||
.dialog-inner
|
||||
p.notice
|
||||
| The master mix is the audio used for session recordings and live broadcasts. Changes to the master mix are global.
|
||||
| The master mix does not include voice chat or the metronome. Any user in the session may use the volume and pan controls
|
||||
| below to make adjustments to the master mix.
|
||||
= react_component 'SessionMasterMix', {}
|
||||
a.button-orange.close-button layout-action="close" CLOSE
|
||||
Loading…
Reference in New Issue