diff --git a/web/app/assets/javascripts/react-components/SessionScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionScreen.js.jsx.coffee
index 1b3685bcb..79b346147 100644
--- a/web/app/assets/javascripts/react-components/SessionScreen.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionScreen.js.jsx.coffee
@@ -4,7 +4,7 @@ SessionActions = @SessionActions
@SessionScreen = React.createClass({
- mixins: [Reflux.listenTo(@AppStore,"onAppInit")]
+ mixins: [Reflux.listenTo(@AppStore,"onAppInit"), Reflux.listenTo(@SessionActions.allowLeaveSession, "onAllowLeaveSession")]
render: () ->
`
@@ -29,8 +29,9 @@ SessionActions = @SessionActions
componentDidMount: () ->
@logger = context.JK.logger
- beforeShow: (data) =>
+ beforeShow: (data) ->
@logger.debug("session beforeShow")
+ @allowLeave = false
afterShow: (data) ->
@logger.debug("session afterShow")
@@ -38,14 +39,30 @@ SessionActions = @SessionActions
SessionActions.joinSession.trigger(data.id)
beforeHide: () ->
- @logger.debug("session beforeHide")
+ context.JK.HelpBubbleHelper.clearJamTrackGuide();
- beforeLeave: () ->
- @logger.debug("session beforeLeave")
+ beforeLeave: (data) ->
+ @logger.debug("session beforeLeave", @allowLeave)
+
+ if @allowLeave
+ return true
+ else
+ leaveSessionWarningDialog = new context.JK.LeaveSessionWarningDialog(context.JK.app,
+ () =>
+ @allowLeave = true
+ context.location.hash = data.hash
+ )
+
+ leaveSessionWarningDialog.initialize()
+ @app.layout.showDialog('leave-session-warning')
+ return false
beforeDisconnect: () ->
@logger.debug("session beforeDisconnect")
+ onAllowLeaveSession: () ->
+ @allowLeave = true
+
onAppInit: (@app) ->
screenBindings = {
diff --git a/web/app/assets/javascripts/react-components/SessionTrackVU.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionTrackVU.js.jsx.coffee
index 5374a6956..d378136d7 100644
--- a/web/app/assets/javascripts/react-components/SessionTrackVU.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionTrackVU.js.jsx.coffee
@@ -16,11 +16,11 @@ context = window
for i in [0..this.props.lightCount-1]
lightClass = if i >= redSwitch then 'vu-red-off' else 'vu-green-off'
- lightClasses = React.addons.classSet('vulight', 'vu' + i, lightClass)
+ lightClasses = classNames('vulight', 'vu' + i, lightClass)
- lights.push(`
| `)
+ lights.push(`
| `)
- tableClasses = React.addons.classSet('vu', 'horizontal', this.props.side + '-' + this.state.mixers.mixer.mixerId)
+ tableClasses = classNames('vu', 'horizontal', this.props.side + '-' + this.state.mixers.mixer.mixerId)
`
@@ -32,11 +32,11 @@ context = window
for i in [0..this.props.lightCount-1].reverse()
lightClass = if (i >= redSwitch) then "vu-red-off" else "vu-green-off"
- lightClasses = React.addons.classSet('vulight', 'vu' + i, lightClass)
+ lightClasses = classNames('vulight', 'vu' + i, lightClass)
- lights.push(`
|
`)
+ lights.push(` |
`)
- tableClasses = React.addons.classSet('vu', 'vertical', this.props.side + '-' + this.state.mixers.mixer.mixerId)
+ tableClasses = classNames('vu', 'vertical', this.props.side + '-' + this.state.mixers.mixer.mixerId)
`
{lights}
diff --git a/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
index 1778c6d2c..c766d4651 100644
--- a/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
@@ -32,7 +32,7 @@ MixerActions = @MixerActions
muteMixer = this.state.mixers.muteMixer
- classes = React.addons.classSet({
+ classes = classNames({
'track-icon-mute': true
'enabled' : !muteMixer.mute
'muted' : muteMixer.mute
diff --git a/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee b/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee
index d815e60c0..41ff315f6 100644
--- a/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee
+++ b/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee
@@ -4,5 +4,5 @@ context = window
joinSession: {}
leaveSession: {}
resyncServer: {asyncResult: true}
- myTracksChanged: {}
+ mixersChanged: {}
})
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee
index b92e0055c..3233de9b8 100644
--- a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee
+++ b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee
@@ -17,15 +17,12 @@ MIX_MODES = context.JK.MIX_MODES;
@muteBothMasterAndPersonalGroups = [ChannelGroupIds.AudioInputMusicGroup, ChannelGroupIds.MediaTrackGroup,
ChannelGroupIds.JamTrackGroup, ChannelGroupIds.MetronomeGroup]
-
@organize()
updateMixers: (type, text, @masterMixers, @personalMixers) ->
@organize()
- if @session.inSession() && text == 'RebuildAudioIoControl'
- SessionActions.myTracksChanged.trigger()
@@ -62,7 +59,7 @@ MIX_MODES = context.JK.MIX_MODES;
localMediaMixers = @mixersForGroupIds(@mediaTrackGroups, MIX_MODES.MASTER)
peerLocalMediaMixers = @mixersForGroupId(ChannelGroupIds.PeerMediaTrackGroup, MIX_MODES.MASTER)
- logger.debug("localMediaMixers", localMediaMixers)
+ #logger.debug("localMediaMixers", localMediaMixers)
#logger.debug("peerLocalMediaMixers", peerLocalMediaMixers)
# get the server data regarding various media tracks
@@ -263,7 +260,7 @@ MIX_MODES = context.JK.MIX_MODES;
else if oppositeMixer.group_id != ChannelGroupIds.AudioInputMusicGroup
logger.error("found local mixer in opposite mode that was not of groupID: AudioInputMusicGroup", mixer, oppositeMixer)
else
- logger.debug("local track is not present: ", track, mixer)
+ logger.debug("local track is not present: ", track, @allMixers)
else
switch @mixMode
when MIX_MODES.MASTER
@@ -459,3 +456,6 @@ MIX_MODES = context.JK.MIX_MODES;
context.JK.VuHelpers.updateVU2('vul', mixer, value)
# Do the right
context.JK.VuHelpers.updateVU2('vur', mixer, value)
+
+ getTrackInfo: () ->
+ context.JK.TrackHelpers(context.jamClient, @masterMixers)
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee b/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee
index 829f9c29c..cdb0908a0 100644
--- a/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee
@@ -13,7 +13,6 @@ 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)
context.JK.HandleVolumeChangeCallback2 = @handleVolumeChangeCallback
context.JK.HandleMetronomeCallback2 = @handleMetronomeCallback
@@ -104,6 +103,8 @@ MIX_MODES = context.JK.MIX_MODES;
# TODO: grab correct mix mode , line 870 sessionModel.js
@mixers.updateMixers(type, text, masterMixers, personalMixers)
- this.trigger({session: @session, mixers: @mixers})
+ SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo())
+
+ this.trigger({session: @session, mixers: @mixers})
}
)
diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
index da5fa7642..04bd575ff 100644
--- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
@@ -4,6 +4,7 @@ logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS;
+
SessionActions = @SessionActions
@SessionStore = Reflux.createStore(
@@ -24,27 +25,77 @@ SessionActions = @SessionActions
sessionPageEnterDeferred: null
gearUtils: null
sessionUtils: null
+ joinDeffered: null
+ recordingModel: null
+ currentTrackChanges: 0
init: ->
# Register with the app store to get @app
- this.listenTo(context.AppStore, this.onAppInit);
+ this.listenTo(context.AppStore, this.onAppInit)
onAppInit: (@app) ->
@gearUtils = context.JK.GearUtilsInstance
@sessionUtils = context.JK.SessionUtils
+ @recordingModel = new context.JK.RecordingModel(@app, this, rest, context.jamClient);
+
+ onWatchedInputs: (inputTracks) ->
+
+ logger.debug("obtained tracks at start of session")
+ @sessionPageEnterDeferred.resolve(inputTracks);
+ @sessionPageEnterDeferred = null
+
+ onMixersChanged: (type, text, trackInfo) ->
+
+ return unless @inSession()
+
+ if text == 'RebuildAudioIoControl'
+ if @backendMixerAlertThrottleTimer
+ clearTimeout(@backendMixerAlertThrottleTimer)
+
+ @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
+
+ # we will get at least one BACKEND_MIXER_CHANGE that corresponds to the backend doing a 'audio pause', which won't matter much
+ # 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 = null
+
+ return
+
+
+ // wait until we are fully in session before trying to sync tracks to server
+ if @joinDeferred
+ @joinDeferred
+ .done(()=>
+ @syncTracks()
+
+ , 100)
+ else if @session.inSession() && text == 'RebuildMediaControl'
+ SessionActions.mediaTracksChanged.trigger(@mixers.getTrackInfo())
+ else if @session.inSession() && text == 'RebuildRemoteUserControl'
+ SessionActions.otherTracksChanged.trigger(@mixers.getTrackInfo())
+
onJoinSession: (sessionId) ->
# initialize webcamViewer
if gon.global.video_available && gon.global.video_available != "none"
- webcamViewer.beforeShow()
+ @webcamViewer.beforeShow()
# double-check that we are connected to the server via websocket
return unless @ensureConnected()
+ # just make double sure a previous session state is cleared out
+ @sessionEnded()
+
# update the session data to be empty
@updateCurrentSession(null)
@@ -153,7 +204,7 @@ SessionActions = @SessionActions
# tell the server we want to join
- rest.joinSession({
+ @joinDeferred = rest.joinSession({
client_id: @app.clientId,
ip_address: context.JK.JamServer.publicIP,
as_musician: true,
@@ -177,7 +228,7 @@ SessionActions = @SessionActions
else
context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.join);
- #recordingModel.reset();
+ @recordingModel.reset(response.id);
context.jamClient.JoinSession({sessionID: response.id});
@@ -417,7 +468,96 @@ SessionActions = @SessionActions
context.JK.JamServer.connected
+ # called by anyone wanting to leave the session with a certain behavior
+ onLeaveSession: (behavior) ->
+ logger.debug("attempting to leave session", behavior)
+ if behavior.notify
+ @app.layout.notify(behavior.notify)
+ SessionActions.allowLeaveSession.trigger()
+ if behavior.location
+ if jQuery.isNumeric(behavior.location)
+ window.history.go(behavior.location)
+ else
+ window.location = behavior.location
+ else
+ logger.warn("no location specified in leaveSession action", behavior)
+ window.location = '/client#/home'
+
+ if gon.global.video_available && gon.global.video_available != "none"
+ @webcamViewer.setVideoOff()
+
+ @leaveSession()
+
+ @sessionUtils.SessionPageLeave()
+
+ leaveSession: () ->
+
+ if @joinDeferred?.state() == 'resolved'
+ deferred = new $.Deferred()
+
+ @recordingModel.stopRecordingIfNeeded()
+ .always(()=>
+ @performLeaveSession(deferred)
+ )
+
+ performLeaveSession: (deferred) ->
+
+ logger.debug("SessionModel.leaveCurrentSession()")
+ # TODO - sessionChanged will be called with currentSession = null\
+
+ # leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long
+ # time, for that entire duration you'll still be sending voice data to the other users.
+ # this may be bad if someone decides to badmouth others in the left-session during this time
+ logger.debug("performLeaveSession: calling jamClient.LeaveSession for clientId=" + @app.clientId)
+ context.jamClient.LeaveSession({ sessionID: @currentSessionId })
+ @leaveSessionRest(@currentSessionId)
+ .done(=>
+ deferred.resolve(arguments[0], arguments[1], arguments[2]))
+ .fail(=>
+ deferred.reject(arguments[0], arguments[1], arguments[2]);
+ )
+
+ # 'unregister' for callbacks
+ context.jamClient.SessionRegisterCallback("");
+ #context.jamClient.SessionSetAlertCallback("");
+ context.jamClient.SessionSetConnectionStatusRefreshRate(0);
+
+ @sessionEnded()
+
+ this.trigger(new context.SessionHelper(@app, @currentSession))
+
+ sessionEnded: () ->
+ # cleanup
+
+ context.JK.JamServer.unregisterMessageCallback(context.JK.MessageType.SESSION_JOIN, @trackChanges);
+ context.JK.JamServer.unregisterMessageCallback(context.JK.MessageType.SESSION_DEPART, @trackChanges);
+ context.JK.JamServer.unregisterMessageCallback(context.JK.MessageType.TRACKS_CHANGED, @trackChanges);
+ context.JK.JamServer.unregisterMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, @trackChanges);
+
+ if @sessionPageEnterDeferred?
+ @sessionPageEnterDeferred.reject('session_over')
+ @sessionPageEnterDeferred = null
+
+ if @backendMixerAlertThrottleTimer
+ clearTimeout(@backendMixerAlertThrottleTimer)
+ @backendMixerAlertThrottleTimer = null
+
+ @userTracks = null;
+ @startTime = null;
+
+ if @joinDeffered?.state() == 'resolved'
+ $(document).trigger(EVENTS.SESSION_ENDED, {session: {id: @currentSessionId}})
+
+ @currentTrackChanges = 0
+ @currentSession = null
+ @joinDeferred = null
+ @currentSessionId = null
+ @currentParticipants = {}
+ @previousAllTracks = {userTracks: [], backingTracks: [], metronomeTracks: []}
+ @openBackingTrack = null
+ @shownAudioMediaMixerHelp = false
+ @controlsLockedForJamTrackRecording = false;
}
)
\ No newline at end of file
diff --git a/web/app/assets/javascripts/recordingModel.js b/web/app/assets/javascripts/recordingModel.js
index 4f0b84e00..ebfff5ca8 100644
--- a/web/app/assets/javascripts/recordingModel.js
+++ b/web/app/assets/javascripts/recordingModel.js
@@ -18,7 +18,7 @@
context.JK = context.JK || {};
var logger = context.JK.logger;
- context.JK.RecordingModel = function(app, sessionModel, _rest, _jamClient) {
+ context.JK.RecordingModel = function(app, _rest, _jamClient) {
var currentRecording = null; // the JSON response from the server for a recording
var currentOrLastRecordingId = null;
var currentRecordingId = null;
@@ -31,7 +31,7 @@
var waitingOnStopTimer = null;
var jamClient = _jamClient;
- var sessionModel = sessionModel;
+ var sessionId = null;
var $self = $(this);
function isRecording (recordingId) {
@@ -46,7 +46,7 @@
}
/** called every time a session is joined, to ensure clean state */
- function reset() {
+ function reset(_sessionId) {
currentlyRecording = false;
waitingOnServerStop = false;
waitingOnClientStop = false;
@@ -57,6 +57,7 @@
currentRecording = null;
currentRecordingId = null;
stoppingRecording = false;
+ sessionId = _sessionId
}
@@ -84,7 +85,7 @@
currentlyRecording = true;
stoppingRecording = false;
- currentRecording = rest.startRecording({"music_session_id": sessionModel.id()})
+ currentRecording = rest.startRecording({"music_session_id": sessionId})
.done(function(recording) {
currentRecordingId = recording.id;
currentOrLastRecordingId = recording.id;
diff --git a/web/app/assets/javascripts/scheduled_session.js.erb b/web/app/assets/javascripts/scheduled_session.js.erb
index 11891e938..021c90bb7 100644
--- a/web/app/assets/javascripts/scheduled_session.js.erb
+++ b/web/app/assets/javascripts/scheduled_session.js.erb
@@ -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#/session/' + sessionId;
+ context.location = '/client#/session2/' + sessionId;
};
if (createSessionSettings.createType == '<%= MusicSession::CREATE_TYPE_START_SCHEDULED%>') {
diff --git a/web/app/assets/javascripts/trackHelpers.js b/web/app/assets/javascripts/trackHelpers.js
index ec9c8771d..f2be21ea5 100644
--- a/web/app/assets/javascripts/trackHelpers.js
+++ b/web/app/assets/javascripts/trackHelpers.js
@@ -16,12 +16,14 @@
// take all necessary arguments to complete its work.
context.JK.TrackHelpers = {
- getTrackInfo: function(jamClient) {
+ getTrackInfo: function(jamClient, masterTracks) {
- var allTracks = context.jamClient.SessionGetAllControlState(true);
+ if(masterTracks === undefined) {
+ masterTracks = context.jamClient.SessionGetAllControlState(true);
+ }
- var userTracks = context.JK.TrackHelpers.getUserTracks(jamClient, allTracks);
- var backingTracks = context.JK.TrackHelpers.getBackingTracks(jamClient, allTracks);
+ var userTracks = context.JK.TrackHelpers.getUserTracks(jamClient, masterTracks);
+ var backingTracks = context.JK.TrackHelpers.getBackingTracks(jamClient, masterTracks);
var metronomeTracks = context.JK.TrackHelpers.getTracks(jamClient, ChannelGroupIds.MetronomeGroup);
return {
diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js
index af46ad1b1..8a30cc099 100644
--- a/web/app/assets/javascripts/utils.js
+++ b/web/app/assets/javascripts/utils.js
@@ -22,6 +22,8 @@
var os = null;
+ var reactHovers = []
+
context.JK.stringToBool = function (s) {
switch (s.toLowerCase()) {
case "true":
@@ -217,6 +219,11 @@
if(!options) options = {};
+ context._.each(reactHovers, function(react) {
+ reactHovers.btOff();
+ })
+ reactHovers = []
+
function waitForBubbleHover($bubble) {
$bubble.hoverIntent({
over: function() {
@@ -235,6 +242,7 @@
options.trigger = 'none'
options.clickAnywhereToClose = true
+ options.closeWhenOthersOpen = true
options.preShow = function(container) {
var reactElement = context[reactElementName]
if(!reactElementName) {
diff --git a/web/app/assets/stylesheets/client/react-components/SessionScreen.css.scss b/web/app/assets/stylesheets/client/react-components/SessionScreen.css.scss
index 796e053e2..8796f4553 100644
--- a/web/app/assets/stylesheets/client/react-components/SessionScreen.css.scss
+++ b/web/app/assets/stylesheets/client/react-components/SessionScreen.css.scss
@@ -301,6 +301,8 @@
background-repeat:no-repeat;
text-align: center;
margin-left:10px;
+ //-webkit-transform: rotate(7deg); /* Chrome, Safari, Opera */
+ //transform: rotate(7deg);
}
.track-icon-equalizer {