diff --git a/app/assets/javascripts/AAB_message_factory.js b/app/assets/javascripts/AAB_message_factory.js index 73404ecd5..069310cab 100644 --- a/app/assets/javascripts/AAB_message_factory.js +++ b/app/assets/javascripts/AAB_message_factory.js @@ -51,7 +51,7 @@ var data = {}; return client_container(msg.PING_REQUEST, route_to_client(client_id), data); }; - // + // Heartbeat message factory.heartbeat = function() { var data = {}; diff --git a/app/assets/javascripts/JamServer.js b/app/assets/javascripts/JamServer.js index 68980405d..0fc89a413 100644 --- a/app/assets/javascripts/JamServer.js +++ b/app/assets/javascripts/JamServer.js @@ -140,6 +140,11 @@ } }); + server.registerMessageCallback(context.JK.MessageType.USER_JOINED_MUSIC_SESSION, function(header, payload) { + context.JK.refreshMusicSession(payload.session_id); + }); + + // TODO: not used server.registerMessageCallback(context.JK.MessageType.LOGIN_MUSIC_SESSION_ACK, function(header, payload) { if (context.jamClient !== undefined) { diff --git a/app/assets/javascripts/createSession.js b/app/assets/javascripts/createSession.js index 348026c09..f3d6e207f 100644 --- a/app/assets/javascripts/createSession.js +++ b/app/assets/javascripts/createSession.js @@ -39,7 +39,6 @@ Message from Seth on sequence for creating/joining sessions: function(response) { var newSessionId = response.id; self.location = '#/session/' + newSessionId; - context.JK.joinMusicSession(newSessionId); } ); evt.preventDefault(); diff --git a/app/assets/javascripts/joinSession.js b/app/assets/javascripts/joinSession.js index ae1e372a4..dd7a404e7 100644 --- a/app/assets/javascripts/joinSession.js +++ b/app/assets/javascripts/joinSession.js @@ -21,14 +21,13 @@ type: "POST", url: url, data: data - }).done( - function(response) { - if (client !== undefined) - { - client.JoinSession({ sessionID: session_id }); - } + }).done(function (response) { + context.JK.Sessions.JoinSession(session_id); + if (client !== undefined) { + client.JoinSession({ sessionID: session_id }); } - ); + context.JK.refreshMusicSession(session_id); + }); }; })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/leaveSession.js b/app/assets/javascripts/leaveSession.js new file mode 100644 index 000000000..ef6b64668 --- /dev/null +++ b/app/assets/javascripts/leaveSession.js @@ -0,0 +1,30 @@ +(function(context,$) { + + context.JK = context.JK || {}; + + context.JK.leaveMusicSession = function(session_id) { + var logger = context.JK.logger; + var server = context.JK.JamServer; + var client = context.jamClient; + + if (!server.signedIn) + { + logger.log("Can't leave a session because the client is not connected."); + return; + } + + logger.log("Leaving session: " + session_id); + + var url = "/api/participants/" + server.clientID; + $.ajax({ + type: "DELETE", + url: url, + }).done(function (response) { + context.JK.Sessions.LeaveSession(session_id); + if (client !== undefined) { + client.LeaveSession({ sessionID: session_id }); + } + }); + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/refreshSession.js b/app/assets/javascripts/refreshSession.js new file mode 100644 index 000000000..a517cf3c4 --- /dev/null +++ b/app/assets/javascripts/refreshSession.js @@ -0,0 +1,63 @@ +(function(context,$) { + + context.JK = context.JK || {}; + + context.JK.refreshMusicSession = function(session_id) { + var logger = context.JK.logger; + var server = context.JK.JamServer; + var client = context.jamClient; + + if (!server.signedIn) + { + logger.log("Can't refresh a session because the client is not connected."); + return; + } + + function _toJamClientParticipant(participant) { + return { + userID : "", + clientID : participant.client_id, + tcpPort : 0, + udpPort : 0, + localIPAddress : "", + globalIPAddress : "", + natType : "", + latency : 0 + }; + } + + logger.log("Refreshing session: " + session_id); + + var url = "/api/sessions/" + session_id; + $.ajax({ + type: "GET", + url: url + }).done(function (response) { + logger.log("Session:"); + logger.log(response); + + var changes = context.JK.Sessions.UpdateSessionParticipants(session_id, response.participants); + + logger.log("Changes:"); + logger.log(changes); + + if (client !== undefined) + { + var session = { sessionID: session_id }; + + $.each(changes.removed, function(index, participant) { + if (participant.client_id != server.clientID) { + client.ParticipantLeft(session, _toJamClientParticipant(participant)); + } + }); + + $.each(changes.added, function(index, participant) { + if (participant.client_id != server.clientID) { + client.ParticipantJoined(session, _toJamClientParticipant(participant)); + } + }); + } + }); + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/session.js b/app/assets/javascripts/session.js index 6f60bdfb2..43cf317b7 100644 --- a/app/assets/javascripts/session.js +++ b/app/assets/javascripts/session.js @@ -5,12 +5,25 @@ var logger = context.JK.logger; var tracks = {}; + // TODO: This is a hack for now so we can have the session id in beforeHide + var hack_session_id; + function afterShow(data) { var sessionId = data.id; + hack_session_id = sessionId; $.ajax({ type: "GET", url: "/api/sessions/" + sessionId }).done(renderSession); + + context.JK.joinMusicSession(sessionId); + } + + function beforeHide(data) { + // TODO: data is empty here - how to get the session id? + //var sessionId = data.id; + var sessionId = hack_session_id; + context.JK.leaveMusicSession(sessionId); } function renderSession(sessionData) { @@ -52,6 +65,8 @@ function _userJoinedSession() { logger.debug(arguments); + // TODO: This doesn't get the payload of the notification. + // Do we need two different notification mechanisms (app and JamServer)? } function deleteSession(evt) { @@ -73,7 +88,8 @@ this.initialize = function() { events(); screenBindings = { - 'afterShow': afterShow + 'afterShow': afterShow, + 'beforeHide': beforeHide, }; app.bindScreen('session', screenBindings); app.subscribe(JK.MessageType.USER_JOINED_MUSIC_SESSION, _userJoinedSession); diff --git a/app/assets/javascripts/sessionModel.js b/app/assets/javascripts/sessionModel.js new file mode 100644 index 000000000..769113e9d --- /dev/null +++ b/app/assets/javascripts/sessionModel.js @@ -0,0 +1,64 @@ +// The session model contains information about the music +// sessions that the current client has joined. +(function(context,$) { + + context.JK = context.JK || {}; + var logger = context.JK.logger; + + var sessions = {} + + sessions.instances = {}; + + sessions.JoinSession = function(session_id) { + if (sessions.instances[session_id] !== undefined) { + logger.error("ERROR: Joined a session twice: " + session_id); + return; + } + + sessions.instances[session_id] = { + id: session_id, + participants: {} + }; + }; + + sessions.LeaveSession = function(session_id) { + if (sessions.instances[session_id] !== undefined) { + delete sessions.instances[session_id]; + } + }; + + sessions.UpdateSessionParticipants = function(session_id, participants) { + var added = []; + var removed = []; + var session = sessions.instances[session_id]; + + if (session === undefined) { + logger.error("ERROR: Unknown session: " + session_id); + return; + } + + var toBeRemoved = $.extend({}, session.participants); + + $.each(participants, function (index, participant) { + if (session.participants[participant.client_id] === undefined) + { + session.participants[participant.client_id] = participant; + added.push(participant); + } + else + { + delete toBeRemoved[participant.client_id]; + } + }); + + $.each(toBeRemoved, function(client_id, participant) { + delete session.participants[client_id]; + removed.push(participant); + }); + + return { added: added, removed: removed }; + }; + + context.JK.Sessions = sessions; + + })(window,jQuery); diff --git a/app/controllers/api_music_sessions_controller.rb b/app/controllers/api_music_sessions_controller.rb index d07420006..312685b67 100644 --- a/app/controllers/api_music_sessions_controller.rb +++ b/app/controllers/api_music_sessions_controller.rb @@ -90,16 +90,21 @@ class ApiMusicSessionsController < ApiController end # send out notification to queue to the rest of the session - user_joined = @message_factory.user_joined_music_session(current_user.id, current_user.name) + user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.name) @mq_router.user_publish_to_session(@music_session, current_user, user_joined, sender = {:client_id => @connection.client_id}) respond_with @connection, responder: ApiResponder, :location => api_session_participant_detail_url(@connection.client_id) end def participant_delete + @music_session = nil + @connection = nil ConnectionManager.active_record_transaction do |connection_manager| @connection = Connection.find_by_client_id(params[:id]) + unless @connection.nil? + @music_session = MusicSession.find(@connection.music_session_id) + end if @connection.nil? raise JamArgumentError, "no client found with specified client_id #{id}" @@ -112,6 +117,13 @@ class ApiMusicSessionsController < ApiController connection_manager.leave_music_session(current_user.id, @connection.client_id, @connection.music_session_id) end + unless @music_session.nil? + # send out notification to queue to the rest of the session + # TODO: we should rename the notification to music_session_participants_change or something + user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.name) + @mq_router.user_publish_to_session(@music_session, current_user, user_joined, sender = {:client_id => @connection.client_id}) + end + respond_with @connection, responder: ApiResponder end end