This commit is contained in:
Seth Call 2015-06-17 19:03:01 -05:00
parent a769dd37bf
commit 7a803bb682
29 changed files with 486 additions and 110 deletions

View File

@ -78,10 +78,10 @@
if (type === 2) { // BACKEND_MIXER_CHANGE
context.SessionActions.mixersChanged(type, text)
context.MixerActions.mixersChanged(type, text)
if(context.JK.CurrentSessionModel)
context.JK.CurrentSessionModel.onBackendMixerChanged(type, text)
//if(context.JK.CurrentSessionModel)
// context.JK.CurrentSessionModel.onBackendMixerChanged(type, text)
}
else if (type === ALERT_NAMES.NO_VALID_AUDIO_CONFIG) { // NO_VALID_AUDIO_CONFIG
if(context.JK.GearUtilsInstance && context.JK.GearUtilsInstance.isRestartingAudio()) {

View File

@ -31,4 +31,7 @@ panHelper = class PanHelper
else
Math.round(value)
convertPercentToPanForDisplay: (percent) ->
Math.abs(context.JK.PanHelpers.convertPercentToPan(percent))
context.JK.PanHelpers = new panHelper()

View File

@ -4,5 +4,6 @@
//= require ./react-components/stores/SessionStore
//= require ./react-components/stores/MixerStore
//= require ./react-components/stores/SessionMyTracksStore
//= require ./react-components/stores/SessionOtherTracksStore
//= require_directory ./react-components/stores
//= require_directory ./react-components

View File

@ -2,8 +2,16 @@ context = window
@SessionInviteMusiciansBtn = React.createClass({
openInviteDialog : (e) ->
e.preventDefault()
#friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', sessionId);
#inviteMusiciansUtil.loadFriends();
#$(friendInput).show();
render: () ->
`<a className="session-invite-musicians">
`<a className="session-invite-musicians" onClick={this.openInviteDialog}>
<img src="/assets/content/icon_add.png" width="19" height="19" />
Invite Musicians
</a>`
})

View File

@ -4,76 +4,93 @@ MixerActions = @MixerActions
@SessionMyTrack = React.createClass({
mixins: [Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged")]
onInputsChanged: (sessionMixers) ->
mixers = sessionMixers.mixers
newMixers = mixers.findMixerForTrack.apply(mixers, this.props.mixerFinder)
this.setState({mixers: newMixers})
getInitialState: () ->
{mixers: this.props.mixers}
handleMute: (e) ->
e.preventDefault()
unless this.props.mixers.mixer
logger.debug("ignoring mute; no mixer")
return
muting = $(e.currentTarget).is('.enabled')
MixerActions.mute([this.state.mixers.mixer, this.state.mixers.oppositeMixer], muting)
MixerActions.mute([this.props.mixers.mixer, this.props.mixers.oppositeMixer], muting)
render: () ->
muteMixer = this.state.mixers.muteMixer
vuMixer = this.state.mixers.vuMixer
muteMixer = this.props.mixers.muteMixer
vuMixer = this.props.mixers.vuMixer
muteMixerId = muteMixer?.id
classes = classNames({
'track-icon-mute': true
'enabled' : !muteMixer.mute
'muted' : muteMixer.mute
'enabled' : !muteMixer?.mute
'muted' : muteMixer?.mute
})
pan = if this.props.mixers.mixer? then this.props.mixers.mixer.pan else 0
panStyle = {
transform: "rotate(#{this.state.mixers.mixer.pan}deg)"
WebkitTransform: "rotate(#{this.state.mixers.mixer.pan}deg)"
transform: "rotate(#{pan}deg)"
WebkitTransform: "rotate(#{pan}deg)"
}
`<div className="session-track my-track">
<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.state.mixers} />
<div className="track-buttons">
<div className={classes} data-control="mute" data-mixer-id={muteMixer.id} onClick={this.handleMute}/>
<div className="track-icon-pan" style={panStyle}/>
<div className="track-icon-equalizer" />
<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 className="track-icon-equalizer" />
</div>
<br className="clearall"/>
</div>
<br className="clearall"/>
</div>
<br className="clearall"/>
</div>`
componentDidMount: () ->
$root = jQuery(this.getDOMNode())
console.log("SessionSetUserName", this.props.clientId, this.props.name)
context.jamClient.SessionSetUserName(this.props.clientId, this.props.name)
$root = $(this.getDOMNode())
$mute = $root.find('.track-icon-mute')
$pan = $root.find('.track-icon-pan')
context.JK.interactReactBubble(
$mute,
'SessionTrackVolumeHover',
{mixers:this.state.mixers, mixerFinder: this.props.mixerFinder},
() =>
{mixers:this.props.mixers, mixerFinder: this.props.mixerFinder}
,
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
context.JK.interactReactBubble(
$pan,
'SessionTrackPanHover',
{mixers:this.state.mixers, mixerFinder: this.props.mixerFinder},
() =>
{mixers:this.props.mixers, mixerFinder: this.props.mixerFinder}
,
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
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)
})

View File

@ -1,9 +1,6 @@
context = window
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
@SessionMyTracks = React.createClass({
mixins: [Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
@ -22,16 +19,15 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
for track in participant.tracks
# try to find mixer info for this track
mixerFinder = [participant.client_id, track, true]
mixerFinder = [participant.client_id, track, true] # so that other callers can re-find their mixer data
mixerData = mixers.findMixerForTrack(participant.client_id, track, true)
mixerData.mixerFinder = mixerFinder # so that other callers can re-find their mixer data
# 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})
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, name: name, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id})
# TODO: also deal with chat

View File

@ -0,0 +1,119 @@
context = window
MixerActions = @MixerActions
@SessionOtherTrack = React.createClass({
handleMute: (e) ->
e.preventDefault()
unless this.props.hasMixer
logger.debug("ignoring mute; no mixer")
return
muting = $(e.currentTarget).is('.enabled')
MixerActions.mute([this.props.mixers.mixer, this.props.mixers.oppositeMixer], muting)
render: () ->
# today, all mixers are the same for a remote participant; so just grab the 1st
mixers = if this.props.tracks.length > 0 then this.props.tracks[0].mixers else {}
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
"my-track" : true
"has-mixer" : this.props.hasMixer
"no-mixer" : !this.props.hasMixer
})
pan = if mixers.mixer? then mixers.mixer?.pan else 0
panStyle = {
transform: "rotate(#{pan}deg)"
WebkitTransform: "rotate(#{pan}deg)"
}
`<div className={componentClasses}>
<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={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 className="track-icon-equalizer" />
</div>
<br className="clearall"/>
</div>
<br className="clearall"/>
</div>
</div>`
componentDidMount: () ->
console.log("SessionSetUserName (other)", this.props.clientId, this.props.name)
context.jamClient.SessionSetUserName(this.props.client_id, this.props.name)
$root = $(this.getDOMNode())
$mute = $root.find('.track-icon-mute')
$pan = $root.find('.track-icon-pan')
context.JK.interactReactBubble(
$mute,
'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}
,
{width:235, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
context.JK.interactReactBubble(
$pan,
'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}
,
{width:331, positions:['right', 'left'], offsetParent:$root.closest('.screen')})
unless this.props.hasMixer
$mute.on("mouseenter", false)
$mute.on("mouseleave", false)
$pan.on("mouseentere", false)
$pan.on("mouseleave", false)
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.hasMixer
$mute.off("mouseenter", false)
$mute.off("mouseleave", false)
$pan.off("mouseenter", false)
$pan.off("mouseleave", false)
else
$mute.on("mouseenter", false)
$mute.on("mouseleave", false)
$pan.on("mouseentere", false)
$pan.on("mouseleave", false)
})

View File

@ -1,18 +1,75 @@
context = window
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
@SessionOtherTracks = React.createClass({
mixins: [Reflux.listenTo(@SessionOtherTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
onInputsChanged: (sessionMixers) ->
session = sessionMixers.session
mixers = sessionMixers.mixers
logger.debug("SessionOtherTracks: onInputsChanged")
participants = []
if session.inSession()
for participant in session.otherParticipants()
tracks = []
name = participant.user.name;
firstTrack = participant.tracks[0]
hasMixer = false
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
mixerData = mixers.findMixerForTrack(participant.client_id, track, false)
if mixerData.mixer?
hasMixer = true
tracks.push(track: track, mixers: mixerData, mixerFinder: mixerFinder)
# 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}
participants.push(participantState)
this.setState(participants:participants, session:session)
render: () ->
noOthers = `<div className="when-empty"></div>`
content = null
participants = []
active = noOthers
noOthers = `<div className="when-empty">No other musicians are in your session.</div>`
if this.state.participants.length > 0
for participant in this.state.participants
participants.push(`<SessionOtherTrack key={participant.client_id} {...participant} />`)
else if this.state.session? && this.state.session.inSession()
content = noOthers
`<div className="session-other-tracks">
<h2>other live tracks</h2>
<SessionInviteMusiciansBtn />
<div className="session-tracks-scroller">
{active}
{content}
<ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
{participants}
</ReactCSSTransitionGroup>
</div>
</div>`
getInitialState:() ->
{participants:[], session: null}
onAppInit: (app) ->
@app = app
})

View File

@ -2,8 +2,19 @@ context = window
@SessionRecordBtn = React.createClass({
datAss: () ->
alert("dat ass")
openRecording: () ->
recording = window.open("/popups/session/#{1}/recording-controls", 'Recording', 'scrollbars=yes,toolbar=no,status=no,height=315,width=350')
window.callMe = @datAss
$(recording).on('load', ()->
alert("loaded")
recording.bling()
)
render: () ->
`<a className="session-record button-grey left">
`<a className="session-record button-grey left" onClick={this.openRecording}>
<img src="/assets/content/icon_settings_sm.png" align="texttop" height="12" width="12"/>
RECORD
</a>`

View File

@ -40,7 +40,7 @@ logger = context.JK.logger
$fader.data('showHelpAboutMediaMixers', this.state.behaviors.showHelpAboutMediaMixers)
context.JK.FaderHelpers.renderFader2($fader, {faderType: 'horizontal', snap:true}, context.JK.PanHelpers.convertPercentToPan)
context.JK.FaderHelpers.renderFader2($fader, {faderType: 'horizontal', snap:true}, context.JK.PanHelpers.convertPercentToPanForDisplay)
# Initialize gain position
MixerActions.initPan(this.state.mixers.mixer)

View File

@ -15,8 +15,8 @@ logger = context.JK.logger
@app = app
render: () ->
`<div className="session-track-settings" onClick={this.onConfigureSettings}>
`<a className="session-track-settings" onClick={this.onConfigureSettings}>
<img src="/assets/content/icon_settings_lg.png" width="18" height="18" />
<span>Settings</span>
</div>`
</a>`
})

View File

@ -2,9 +2,6 @@ context = window
@SessionTrackVU = React.createClass({
getInitialState: () ->
{mixers: this.props.mixers}
render: () ->
lights = []
@ -20,7 +17,7 @@ context = window
lights.push(`<td key={i} width={this.props.lightWidth} height={this.props.lightHeight} className={lightClasses}></td>`)
tableClasses = classNames('vu', 'horizontal', this.props.side + '-' + this.state.mixers.mixer.mixerId)
tableClasses = classNames('vu', 'horizontal', this.props.side + '-' + this.props.mixers.mixer?.id)
`<table className={tableClasses} data-light-count={this.props.lightCount}>
<tr>
@ -36,7 +33,7 @@ context = window
lights.push(`<tr><td key={i} width={this.props.lightWidth} height={this.props.lightHeight} className={lightClasses}></td></tr>`)
tableClasses = classNames('vu', 'vertical', this.props.side + '-' + this.state.mixers.mixer.mixerId)
tableClasses = classNames('vu', 'vertical', this.props.side + '-' + this.props.mixers.mixer?.id)
`<table className={tableClasses} data-light-count={this.props.lightCount}>
{lights}

View File

@ -32,10 +32,13 @@ MixerActions = @MixerActions
muteMixer = this.state.mixers.muteMixer
muteMixerId = muteMixer?.id
volume_left = this.state.mixers.mixer?.volume_left
classes = classNames({
'track-icon-mute': true
'enabled' : !muteMixer.mute
'muted' : muteMixer.mute
'enabled' : !muteMixer?.mute
'muted' : muteMixer?.mute
})
@ -49,10 +52,10 @@ MixerActions = @MixerActions
</div>
<div className="track-label">
<div>Volume</div>
<div>{this.state.mixers.mixer.volume_left}dB</div>
<div>{volume_left}dB</div>
</div>
<SessionTrackGain mixers={this.state.mixers} />
<div className={classes} data-control="mute" data-mixer-id={this.state.mixers.muteMixer.id} onClick={this.handleMute}/>
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
<input type="checkbox" name="mute"/>
<label for="mute">Mute</label>
@ -84,7 +87,7 @@ MixerActions = @MixerActions
# 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)

View File

@ -7,4 +7,6 @@ context = window
panChanged: {}
initPan: {}
mixersChanged: {}
syncTracks: {}
mixerModeChanged: {}
})

View File

@ -3,6 +3,6 @@ context = window
@SessionActions = Reflux.createActions({
joinSession: {}
leaveSession: {}
resyncServer: {asyncResult: true}
mixersChanged: {}
allowLeaveSession: {}
})

View File

@ -27,7 +27,7 @@ MIX_MODES = context.JK.MIX_MODES;
organize: () ->
for masterMixer, i in @masterMixers
for masterMixer in @masterMixers
@allMixers['M' + masterMixer.id] = masterMixer; # populate allMixers by mixer.id
# populate mixer pair
@ -36,7 +36,7 @@ MIX_MODES = context.JK.MIX_MODES;
@mixersByTrackId[masterMixer.id] = mixerPair
mixerPair.master = masterMixer;
for personalMixer, i in @personalMixers
for personalMixer in @personalMixers
@allMixers['P' + personalMixer.id] = personalMixer
@ -222,7 +222,7 @@ MIX_MODES = context.JK.MIX_MODES;
if mixer.client_id == clientId
for groupId in groupIds
if mixer.group_id == groupId
if (mixer.groupId != ChannelGroupIds.UserMusicInputGroup) && !(mixer.id in usedMixers)
if (mixer.groupId != ChannelGroupIds.UserMusicInputGroup) && !(mixer.id of usedMixers)
mixers = foundMixers[mixer.group_id]
if !mixers
mixers = []
@ -365,7 +365,7 @@ MIX_MODES = context.JK.MIX_MODES;
initPan: (mixer) ->
panPercent= context.JK.PanHelpers.convertPanToPercent(mixer.pan)
context.JK.FaderHelpers.setFaderValue(mixer.id, panPercent, mixer.pan)
context.JK.FaderHelpers.setFaderValue(mixer.id, panPercent, Math.abs(mixer.pan))
context.JK.FaderHelpers.showFader(mixer.id)
setMixerPan: (mixer, panPercent) ->
@ -449,7 +449,10 @@ MIX_MODES = context.JK.MIX_MODES;
if mixer
if mixer.stereo # // stereo track
context.JK.VuHelpers.updateVU2('vul', mixer, value)
if mixerId.substr(-4) == "_vul"
context.JK.VuHelpers.updateVU2('vul', mixer, value)
else
context.JK.VuHelpers.updateVU2('vur', mixer, value)
else
if mixerId.substr(-4) == "_vul"
# Do the left
@ -458,4 +461,4 @@ MIX_MODES = context.JK.MIX_MODES;
context.JK.VuHelpers.updateVU2('vur', mixer, value)
getTrackInfo: () ->
context.JK.TrackHelpers(context.jamClient, @masterMixers)
context.JK.TrackHelpers.getTrackInfo(context.jamClient, @masterMixers)

View File

@ -15,6 +15,14 @@ context = window
else
[]
otherParticipants: () ->
others = []
for participant in @participants()
myTrack = @app.clientId == participant.client_id
others.push(participant) unless myTrack
others
# if any participant has the metronome open, then we say this session has the metronome open
isMetronomeOpen: () ->
metronomeOpen = false;
@ -78,3 +86,5 @@ context = window
logger.warn('unable to find participant with clientId: ' + clientId) unless found
found
id: () ->
@session.id

View File

@ -1,6 +1,7 @@
context = window
logger = context.JK.logger
MIX_MODES = context.JK.MIX_MODES;
MIX_MODES = context.JK.MIX_MODES
rest = context.JK.Rest()
@MixerStore = Reflux.createStore(
{
@ -13,6 +14,9 @@ MIX_MODES = context.JK.MIX_MODES;
this.listenTo(context.MixerActions.initGain, this.onInitGain)
this.listenTo(context.MixerActions.initPan, this.onInitPan)
this.listenTo(context.MixerActions.panChanged, this.onPanChanged)
this.listenTo(context.MixerActions.mixersChanged, this.onMixersChanged)
this.listenTo(context.MixerActions.syncTracks, this.onSyncTracks)
this.listenTo(context.MixerActions.mixerModeChanged, this.onMixerModeChanged)
context.JK.HandleVolumeChangeCallback2 = @handleVolumeChangeCallback
context.JK.HandleMetronomeCallback2 = @handleMetronomeCallback
@ -60,11 +64,10 @@ MIX_MODES = context.JK.MIX_MODES;
@session = session
masterMixers = context.jamClient.SessionGetAllControlState(true);
personalMixers = context.jamClient.SessionGetAllControlState(false);
@masterMixers = context.jamClient.SessionGetAllControlState(true);
@personalMixers = context.jamClient.SessionGetAllControlState(false);
# TODO: grab correct mix mode , line 870 sessionModel.js
@mixers = new context.MixerHelper(session, masterMixers, personalMixers, MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(session, @masterMixers, @personalMixers, @mixers?.mixMode || MIX_MODES.PERSONAL)
this.trigger({session: @session, mixers: @mixers})
@ -96,15 +99,51 @@ MIX_MODES = context.JK.MIX_MODES;
onMixersChanged: (type, text) ->
if @mixers
masterMixers = context.jamClient.SessionGetAllControlState(true);
personalMixers = context.jamClient.SessionGetAllControlState(false);
@masterMixers = context.jamClient.SessionGetAllControlState(true);
@personalMixers = context.jamClient.SessionGetAllControlState(false);
# TODO: grab correct mix mode , line 870 sessionModel.js
@mixers.updateMixers(type, text, masterMixers, personalMixers)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @mixers?.mixMode || MIX_MODES.PERSONAL)
SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo())
SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo())
this.trigger({session: @session, mixers: @mixers})
onMixerModeChanged: (mode) ->
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, mode)
this.trigger({session: @session, mixers: @mixers})
onSyncTracks: () ->
logger.debug("MixerStore: onSyncTracks")
unless @session.inSession()
logger.debug("dropping queued up sync tracks because no longer in session")
return
allTracks = @mixers.getTrackInfo()
inputTracks = allTracks.userTracks;
backingTracks = allTracks.backingTracks;
metronomeTracks = allTracks.metronomeTracks;
# create a trackSync request based on backend data
syncTrackRequest = {}
syncTrackRequest.client_id = @app.clientId
syncTrackRequest.tracks = inputTracks
syncTrackRequest.backing_tracks = backingTracks
syncTrackRequest.metronome_open = metronomeTracks.length > 0
syncTrackRequest.id = @session.id()
rest.putTrackSyncChange(syncTrackRequest)
.fail((jqXHR)=>
if jqXHR.status != 404
@app.notify({
"title": "Can't Sync Local Tracks",
"text": "The client is unable to sync local track information with the server. You should rejoin the session to ensure a good experience.",
"icon_url": "/assets/content/icon_alert_big.png"
})
else
logger.debug("Unable to sync local tracks because session is gone.")
)
}
)

View File

@ -0,0 +1,21 @@
$ = jQuery
context = window
logger = context.JK.logger
@SessionOtherTracksStore = Reflux.createStore(
{
init: ->
# Register with the app store to get @app
this.listenTo(context.AppStore, this.onAppInit);
this.listenTo(context.MixerStore, this.onSessionMixerChange)
onAppInit: (@app) ->
@gearUtils = context.JK.GearUtilsInstance
@sessionUtils = context.JK.SessionUtils
onSessionMixerChange: (sessionMixers) ->
this.trigger(sessionMixers)
}
)

View File

@ -2,7 +2,8 @@ $ = jQuery
context = window
logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS;
EVENTS = context.JK.EVENTS
MIX_MODES = context.JK.MIX_MODES
SessionActions = @SessionActions
@ -28,7 +29,7 @@ SessionActions = @SessionActions
joinDeffered: null
recordingModel: null
currentTrackChanges: 0
previousAllTracks: {userTracks: [], backingTracks: [], metronomeTracks: []}
init: ->
# Register with the app store to get @app
@ -50,11 +51,12 @@ SessionActions = @SessionActions
return unless @inSession()
if text == 'RebuildAudioIoControl'
if @backendMixerAlertThrottleTimer
clearTimeout(@backendMixerAlertThrottleTimer)
@backendMixerAlertThrottleTimer = setTimeout(
() =>
@backendMixerAlertThrottleTimer =
setTimeout(() =>
@backendMixerAlertThrottleTimer = null
if @sessionPageEnterDeferred
# this means we are still waiting for the BACKEND_MIXER_CHANGE that indicates we have user tracks built-out/ready
@ -63,25 +65,43 @@ SessionActions = @SessionActions
# so we need to check that we actaully have userTracks before considering ourselves done
if trackInfo.userTracks.length > 0
logger.debug("obtained tracks at start of session")
@sessionPageEnterDeferred.resolve(trackInfo.userTracks);
@sessionPageEnterDeferred.resolve(trackInfo.userTracks)
@sessionPageEnterDeferred = null
return
// wait until we are fully in session before trying to sync tracks to server
# wait until we are fully in session before trying to sync tracks to server
if @joinDeferred
@joinDeferred
.done(()=>
@syncTracks()
MixerActions.syncTracks()
)
, 100)
else if @session.inSession() && text == 'RebuildMediaControl'
SessionActions.mediaTracksChanged.trigger(@mixers.getTrackInfo())
else if @session.inSession() && text == 'RebuildRemoteUserControl'
SessionActions.otherTracksChanged.trigger(@mixers.getTrackInfo())
else if text == 'RebuildMediaControl' || text == 'RebuildRemoteUserControl'
backingTracks = trackInfo.backingTracks
previousBackingTracks = @previousAllTracks.backingTracks
metronomeTracks = trackInfo.metronomeTracks
previousMetronomeTracks = @previousAllTracks.metronomeTracks
# the way we know if backing tracks changes, or recordings are opened, is via this event.
# but we want to report to the user when backing tracks change; so we need to detect change on our own
if !(previousBackingTracks.length == 0 && backingTracks.length == 0) && previousBackingTracks != backingTracks
logger.debug("backing tracks changed", previousBackingTracks, backingTracks)
MixerActions.syncTracks()
else if !(previousMetronomeTracks.length == 0 && metronomeTracks.length == 0) && previousMetronomeTracks != metronomeTracks
logger.debug("metronome state changed ", previousMetronomeTracks, metronomeTracks)
MixerActions.syncTracks()
else
@refreshCurrentSession(true)
@previousAllTracks = trackInfo
else if text == 'Global Peer Input Mixer Mode'
MixerActions.mixerModeChanged(MIX_MODES.MASTER)
else if text == 'Local Peer Stream Mixer Mode'
MixerActions.mixerModeChanged(MIX_MODES.PERSONAL)
onJoinSession: (sessionId) ->
@ -349,7 +369,7 @@ SessionActions = @SessionActions
@requestingSessionRefresh = false
if @pendingSessionRefresh
# and when the request is done, if we have a pending, fire it off again
pendingSessionRefresh = false
@pendingSessionRefresh = false
@refreshCurrentSessionRest(force)
)
@ -389,11 +409,11 @@ SessionActions = @SessionActions
for client_id, participant of newParticipantIds
# grow the 'all participants seen' list
unless (client_id in @participantsEverSeen)
unless (client_id of @participantsEverSeen)
@participantsEverSeen[client_id] = participant;
if client_id in oldParticipantIds
if client_id of oldParticipantIds
# if the participant is here now, and here before, there is still a chance we missed a
# very fast leave/join. So check if joined_session_at is different
if oldParticipantIds[client_id].joined_session_at != participant.joined_session_at
@ -403,7 +423,7 @@ SessionActions = @SessionActions
joins.push(participant);
for client_id, participant of oldParticipantIds
unless (client_id in newParticipantIds)
unless (client_id of newParticipantIds)
# old participant id that's not in new participant ids: Leave
leaves.push(participant);

View File

@ -215,7 +215,7 @@
* @param text
* @param options
*/
context.JK.interactReactBubble = function($element, reactElementName, reactProps, options) {
context.JK.interactReactBubble = function($element, reactElementName, reactPropsCallback, options) {
if(!options) options = {};
@ -248,7 +248,7 @@
if(!reactElementName) {
throw "unknown react element" + reactElementName
}
var element = React.createElement(reactElement, reactProps);
var element = React.createElement(reactElement, reactPropsCallback());
var $container = $(container)

View File

@ -73,21 +73,38 @@
margin: 0;
}
.session-my-tracks {
.session-track {
float:left;
margin: 10px 0;
.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;
color: $ColorTextTypical;
background-color: #242323;
}
.disabled-track-overlay {
width: 0;
height: 0;
position: absolute;
background-color:#555;
border-radius: 6px;
min-height: 76px;
max-width: 210px;
@include border_box_sizing;
}
&.no-mixer {
.disabled-track-overlay {
width: 100%;
height: 100%;
opacity:0.5;
}
}
}
.react-holder {
&.SessionTrackVolumeHover {
height:331px;
@ -231,6 +248,12 @@
}
}
.when-empty {
margin-top:20px;
margin-left:22px;
color:$ColorTextTypical;
overflow:hidden;
}
.session-track {
@ -337,6 +360,8 @@
.session-track-settings {
height:18px;
cursor:pointer;
color:white;
padding-bottom:1px; // to line up with SessionOtherTracks
span {
top: -4px;
@ -344,4 +369,17 @@
left:3px;
}
}
.session-invite-musicians {
height:19px;
cursor: pointer;
color:white;
span {
top:-5px;
position:relative;
left:3px;
}
}
}

View File

@ -5,5 +5,6 @@
*= require client/screen_common
*= require client/content
*= require client/ftue
*= require minimal/recording_controls
*= require minimal/minimal_main
*/

View File

@ -0,0 +1,6 @@
body.recording-controls {
width:100%;
height:100%;
background-color:#404040;
overflow: hidden !important;
}

View File

@ -0,0 +1,9 @@
class PopupsController < ApplicationController
respond_to :html
def recording_controls
render :layout => "minimal"
end
end

View File

@ -18,7 +18,7 @@
<% end %>
<%= render "shared/ad_sense" %>
</head>
<body class="jam">
<body class="minimal jam <%= yield(:page_name) %>">
<div id="minimal-container">
<%= javascript_include_tag "minimal/minimal" %>
<div class="wrapper">

View File

@ -0,0 +1,11 @@
- provide(:page_name, 'recording-controls')
.recording-controls
| IM HERE
javascript:
window.bling = function () {
alert("bling!!")
window.opener.callMe()
}
console.log("window.opener", window.opener)

View File

@ -135,6 +135,10 @@ SampleApp::Application.routes.draw do
# admin-only page to control settings
match '/extras/settings', to: 'extras#settings'
scope '/popups' do
match '/session/:id/recording-controls', to: 'popups#recording_controls'
end
scope '/corp' do
# about routes
match '/about', to: 'corps#about', as: 'corp_about'