diff --git a/pb/src/client_container.proto b/pb/src/client_container.proto index 4acccc86d..aa9fe6a12 100644 --- a/pb/src/client_container.proto +++ b/pb/src/client_container.proto @@ -363,6 +363,7 @@ message SessionJoin { optional string msg = 3; optional int32 track_changes_counter = 4; optional string source_user_id = 5; + optional string client_id = 6; } message SessionDepart { diff --git a/ruby/lib/jam_ruby/message_factory.rb b/ruby/lib/jam_ruby/message_factory.rb index 6b7e98034..3e4789d6a 100644 --- a/ruby/lib/jam_ruby/message_factory.rb +++ b/ruby/lib/jam_ruby/message_factory.rb @@ -404,18 +404,20 @@ module JamRuby ) end - def session_join(session_id, photo_url, source_user_id, msg, track_changes_counter) + # we send session_join to both every one in the session, and also every client belonging to user X + def session_join(session_id, photo_url, source_user_id, msg, track_changes_counter, source_client_id, route_to = CLIENT_TARGET) join = Jampb::SessionJoin.new( :session_id => session_id, :photo_url => photo_url, :source_user_id => source_user_id, :msg => msg, - :track_changes_counter => track_changes_counter + :track_changes_counter => track_changes_counter, + :client_id => source_client_id ) Jampb::ClientMessage.new( :type => ClientMessage::Type::SESSION_JOIN, - :route_to => CLIENT_TARGET, + :route_to => route_to, :session_join => join ) end diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index d86d73d12..076d26043 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -529,15 +529,28 @@ module JamRuby notification_msg = format_msg(NotificationTypes::SESSION_JOIN, {:user => user}) - msg = @@message_factory.session_join( + sessionMsg = @@message_factory.session_join( active_music_session.id, user.photo_url, user.id, notification_msg, - active_music_session.track_changes_counter + active_music_session.track_changes_counter, + connection.client_id, + MessageFactory::CLIENT_TARGET ) - @@mq_router.server_publish_to_session(active_music_session, msg, sender = {:client_id => connection.client_id}) + userMsg = @@message_factory.session_join( + active_music_session.id, + user.photo_url, + user.id, + notification_msg, + active_music_session.track_changes_counter, + connection.client_id, + MessageFactory::USER_TARGET_PREFIX + user.id + ) + + @@mq_router.server_publish_to_session(active_music_session, sessionMsg, sender = {:client_id => connection.client_id}) + @@mq_router.publish_to_user(user.id, userMsg, sender = {:client_id => connection.client_id}) end def send_session_depart(active_music_session, client_id, user, recordingId) diff --git a/ruby/lib/jam_ruby/mq_router.rb b/ruby/lib/jam_ruby/mq_router.rb index 8aec53cde..c7a9ba417 100644 --- a/ruby/lib/jam_ruby/mq_router.rb +++ b/ruby/lib/jam_ruby/mq_router.rb @@ -89,11 +89,14 @@ class MQRouter # sends a message to a user with no checking of permissions (RAW USAGE) # this method deliberately has no database interactivity/active_record objects - def publish_to_user(user_id, user_msg) + def publish_to_user(user_id, user_msg, sender = {:client_id => nil}) @@log.error "EM not running in publish_to_user" unless EM.reactor_running? EM.schedule do - @@log.debug "publishing to user:#{user_id} from server" + sender_client_id = sender[:client_id] + + @@log.debug "publishing to user:#{user_id} from server from client:#{sender_client_id}" + # put it on the topic exchange for users self.class.user_exchange.publish(user_msg, :routing_key => "user.#{user_id}") end diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index 7acd44450..793ca89b1 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -39,6 +39,16 @@ // (Wishing I could write a single function which debug logs the name of the // current function and a JSON stringify of the arguments). + function getClientParentChildRole() { + // 0 = client + // 1 = parent + return 1; + } + + function getParentClientId() { + return null; + } + function OpenSystemBrowser(href) { dbg("OpenSystemBrowser('" + href + "')"); context.window.open(href); @@ -1260,6 +1270,8 @@ this.ClientUpdateStartDownload = ClientUpdateStartDownload; this.ClientUpdateStartUpdate = ClientUpdateStartUpdate; + this.getClientParentChildRole = getClientParentChildRole; + this.getParentClientId = getParentClientId; this.OpenSystemBrowser = OpenSystemBrowser; this.RestartApplication = RestartApplication; this.ShutdownApplication = ShutdownApplication; diff --git a/web/app/assets/javascripts/globals.js b/web/app/assets/javascripts/globals.js index 5fb037cc5..b300cd4f2 100644 --- a/web/app/assets/javascripts/globals.js +++ b/web/app/assets/javascripts/globals.js @@ -10,6 +10,11 @@ context.JK.MIDI_TRACK = 100 + context.JK.CLIENT_ROLE = { + CHILD: 0, + PARENT: 1 + } + context.JK.OS = { WIN32: "Win32", OSX: "MacOSX", 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 d9d31fada..34f68923d 100644 --- a/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee +++ b/web/app/assets/javascripts/react-components/actions/SessionActions.js.coffee @@ -20,4 +20,6 @@ context = window broadcastSuccess: {} broadcastStopped: {} mixdownActive: {} + sessionJoinedByOther: {} + navToSession: {} }) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee index 85dc3a062..7b48ed75f 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 MIX_MODES = context.JK.MIX_MODES +CLIENT_ROLE = context.JK.CLIENT_ROLE JamTrackActions = @JamTrackActions SessionActions = @SessionActions @@ -54,6 +55,19 @@ ConfigureTracksActions = @ConfigureTracksActions RecordingActions.initModel(@recordingModel) @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?) + onSessionJoinedByOther: (payload) -> + clientId = payload.client_id + + parentClientId = context.jamClient.getParentClientId() + if parentClientId? && parentClientId != '' + if parentClientId == clientId + # auto nav to session + logger.debug("autonav to session #{payload.session_id}") + context.SessionActions.navToSession(payload.session_id) + + onNavToSession: (sessionId) -> + context.location = '/client#/session/' + sessionId + onMixdownActive: (mixdown) -> if @currentSession?.jam_track? @currentSession.jam_track.mixdown = mixdown @@ -600,6 +614,18 @@ ConfigureTracksActions = @ConfigureTracksActions shouldVerifyNetwork = musicSession.musician_access; + # old client protection + if !context.jamClient.getClientParentChildRole? + clientRole = CLIENT_ROLE.PARENT + else + clientRole = context.jamClient.getClientParentChildRole() + + if clientRole == CLIENT_ROLE.CHILD + logger.debug("client is configured to act as child. skipping all checks. assuming 0 tracks") + @userTracks = [] + @joinSession() + return + @gearUtils.guardAgainstInvalidConfiguration(@app, shouldVerifyNetwork).fail(() => SessionActions.leaveSession.trigger({location: '/client#/home'}) ).done(() => diff --git a/web/app/assets/javascripts/sidebar.js b/web/app/assets/javascripts/sidebar.js index 19c43bc94..4931fb184 100644 --- a/web/app/assets/javascripts/sidebar.js +++ b/web/app/assets/javascripts/sidebar.js @@ -248,12 +248,17 @@ context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, function(header, payload) { logger.debug("Handling SESSION_JOIN msg " + JSON.stringify(payload)); - // display notification - app.notify({ - "title": "New Session Participant", - "text": payload.msg, - "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) - }); + if (app.clientId != payload.client_id) { + // display notification + app.notify({ + "title": "New Session Participant", + "text": payload.msg, + "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) + }); + + // tell session store that this happened + context.SessionActions.sessionJoinedByOther(payload) + } }); } diff --git a/web/app/assets/stylesheets/client/react-components/SessionTrack.css.scss b/web/app/assets/stylesheets/client/react-components/SessionTrack.css.scss index 351d75ae1..a77016c55 100644 --- a/web/app/assets/stylesheets/client/react-components/SessionTrack.css.scss +++ b/web/app/assets/stylesheets/client/react-components/SessionTrack.css.scss @@ -157,11 +157,16 @@ } } + // for VST width considerations, widen my track and chat track &.my-track { width:235px; max-width:235px; } + &.chat-track { + width:235px; + max-width:235px; + } // media overrides &.backing-track, &.recorded-track, &.jam-track, &.metronome, &.recorded-category, &.jam-track-category {