Merge branch 'master' of bitbucket.org:jamkazam/jam-web

This commit is contained in:
Brian Smith 2012-10-15 08:54:01 -04:00
commit 848154eb33
11 changed files with 322 additions and 104 deletions

View File

@ -0,0 +1,25 @@
(function(context) {
/*
internal logger with no-ops when console is missing.
*/
context.JK = context.JK || {};
var console_methods = [
'log', 'debug', 'info', 'warn', 'error', 'assert',
'clear', 'dir', 'dirxml', 'trace', 'group',
'groupCollapsed', 'groupEnd', 'time', 'timeEnd',
'timeStamp', 'profile', 'profileEnd', 'count',
'exception', 'table'
];
if ('undefined' === typeof(context.console)) {
context.console = {};
$.each(console_methods, function(index, value) {
context.console[value] = $.noop;
});
}
context.JK.logger = context.console;
}(window));

View File

@ -0,0 +1,83 @@
/*
Message builder for communicating over the websocket
*/
(function(context, $) {
context.JK = context.JK || {};
var msg = context.JK.MessageType = {
LOGIN : "LOGIN",
LOGIN_ACK : "LOGIN_ACK",
LOGIN_MUSIC_SESSION : "LOGIN_MUSIC_SESSION",
LOGIN_MUSIC_SESSION_ACK : "LOGIN_MUSIC_SESSION_ACK",
USER_JOINED_MUSIC_SESSION : "USER_JOINED_MUSIC_SESSION",
LEAVE_MUSIC_SESSION : "LEAVE_MUSIC_SESSION",
LEAVE_MUSIC_SESSION_ACK : "LEAVE_MUSIC_SESSION_ACK",
HEARTBEAT : "HEARTBEAT",
TEST_SESSION_MESSAGE : "TEST_SESSION_MESSAGE",
PING_REQUEST : "PING_REQUEST",
PING_ACK : "PING_ACK",
PEER_MESSAGE : "PEER_MESSAGE",
SERVER_GENERIC_ERROR : "SERVER_GENERIC_ERROR",
SERVER_REJECTION_ERROR : "SERVER_REJECTION_ERROR"
};
var route_to = context.JK.RouteToPrefix = {
CLIENT : "client",
SESSION : "session",
SERVER : "server",
USER : "user"
};
var factory = {};
function client_container(type, target, inner) {
var type_field = type.toLowerCase();
var body = { "type" : type, "route_to" : target};
body[type_field] = inner;
return body;
}
function route_to_client(client_id) {
return route_to.CLIENT + ":" + client_id;
}
function route_to_session(session_id) {
return route_to.SESSION + ":" + session_id;
}
// ping the provided client_id
factory.ping = function(client_id) {
var data = {};
return client_container(msg.PING_REQUEST, route_to_client(client_id), data);
};
// create a login message using user/pass
factory.login_with_user_pass = function(username, password) {
var login = { username : username , password : password };
return client_container(msg.LOGIN, route_to.SERVER, login);
};
// create a login message using token (a cookie or similiar)
factory.login_with_token = function(token) {
var login = { token : token };
return client_container(msg.LOGIN, route_to.SERVER, login);
};
// create a music session login message
factory.login_music_session = function(music_session) {
var login_music_session = { music_session : music_session };
return client_container(msg.LOGIN_MUSIC_SESSION, route_to.SERVER, login_music_session);
};
// client-to-client message
factory.client_p2p_message = function(sender_client_id, receiver_client_id, message) {
var peer_message = { "message" : message };
var result = client_container(msg.PEER_MESSAGE, route_to_client(receiver_client_id), peer_message);
result.from = sender_client_id;
return result;
};
context.JK.MessageFactory = factory;
})(window, jQuery);

View File

@ -1,25 +1,26 @@
// The wrapper around the web-socket connection to the server
(function(global, $) {
var server = {};
(function(context, $) {
context.JK = context.JK || {};
var logger = context.JK.logger;
var msg_factory = context.JK.MessageFactory;
// Let socket.io know where WebSocketMain.swf is
WEB_SOCKET_SWF_LOCATION = "assets/flash/WebSocketMain.swf";
var server = {};
server.socket = {};
server.singedIn = false;
server.dispatchTable = {};
// TODO: Create the message factory here
//server.messageFactory = global.message_factory;
server.registerMessageCallback = function(messageType, callback) {
if (server.dispatchTable[messageType] === undefined) {
server.dispatchTable[messageType] = [];
}
server.dispatchTable[messageType].push(callback);
};
server.unregisterMessageCallback = function(messageType, callback) {
if (server.dispatchTable[messageType] !== undefined) {
for(var i = server.dispatchTable.length; i--;) {
@ -30,67 +31,120 @@
}
}
}
if (server.dispatchTable[messageType].length == 0) {
if (server.dispatchTable[messageType].length === 0) {
delete server.dispatchTable[messageType];
}
};
server.connect = function() {
server.registerMessageCallback(LOGIN_ACK, function() { server.signedIn = true; });
logger.log("server.connect");
server.socket = new WebSocket(gon.websocket_gateway_uri);
server.socket.onopen = server.onOpen;
server.socket.onmessage = server.onMessage;
server.socket.onclose = server.onClose;
};
server.onOpen = function() {
logger.log("server.onOpen");
var token, loginMessage;
token = $.cookie("remember_token");
loginMessage = global.message_factory.login_with_token(token);
loginMessage = msg_factory.login_with_token(token);
server.send(loginMessage);
};
server.onMessage = function(e) {
logger.log("server.onMessage");
var message = JSON.parse(e.data),
payload = message[message.type.toLowerCase()],
messageType = message.type.toLowerCase(),
payload = message[messageType],
callbacks = server.dispatchTable[message.type];
if (callbacks !== undefined) {
for(var i = callbacks.length; i--;) {
callbacks[i](payload);
var len = callbacks.length;
for(var i = 0; i < len; i++) {
callbacks[i](messageType, payload);
}
}
else {
console.log("Unexpected message type %s.", message.type);
logger.log("Unexpected message type %s.", message.type);
}
};
server.onClose = function() {
console.log("Socket to server closed.");
logger.log("Socket to server closed.");
if (context.jamClient !== undefined)
{
context.jamClient.connected = false;
}
// TODO: reconnect
};
server.send = function(message) {
server.socket.send(JSON.stringify(message));
var jsMessage = JSON.stringify(message);
logger.log("server.send(" + jsMessage + ")");
if (server !== undefined && server.socket !== undefined && server.socket.send !== undefined) {
server.socket.send(jsMessage);
} else {
logger.log("Dropped message because server connection is closed.");
}
};
server.loginSession = function(sessionId) {
var loginMessage;
if (!signedIn) {
console.log("Not signed in!");
logger.log("Not signed in!");
// TODO: surface the error
return;
}
loginMessage = global.message_factory.login_jam_session(sessionId);
loginMessage = msg_factory.login_jam_session(sessionId);
server.send(loginMessage);
};
global.JamServer = server;
server.sendP2PMessage = function(receiver_id, message) {
logger.log("P2P message from [" + server.clientID + "] to [" + receiver_id + "]: " + message);
var outgoing_msg = msg_factory.client_p2p_message(server.clientID, receiver_id, message);
server.send(outgoing_msg);
};
context.JK.JamServer = server;
})(window, jQuery);
// Message callbacks
server.registerMessageCallback(context.JK.MessageType.LOGIN_ACK, function(type, payload) {
server.signedIn = true;
server.clientID = payload.client_id;
if (context.jamClient !== undefined)
{
context.jamClient.connected = true;
context.jamClient.clientID = server.clientID;
}
});
server.registerMessageCallback(context.JK.MessageType.PEER_MESSAGE, function(type, payload) {
if (context.jamClient !== undefined)
{
context.jamClient.P2PMessageReceived(payload.sender_id, payload.message);
}
});
server.registerMessageCallback(context.JK.MessageType.LOGIN_MUSIC_SESSION_ACK, function(type, payload) {
if (context.jamClient !== undefined)
{
// TODO: modify the LOGIN_MUSIC_SESSION_ACK message to include session_id
context.jamClient.JoinSession({ sessionID : payload.session_id});
}
});
// Callbacks from jamClient
if (context.jamClient !== undefined)
{
context.jamClient.SendP2PMessage.connect(server.sendP2PMessage);
}
})(window, jQuery);

View File

@ -2,6 +2,7 @@
context.JK = context.JK || {};
context.JK.CreateSessionScreen = function(app) {
var logger = context.JK.logger;
function afterShow(data) {}
@ -27,9 +28,11 @@
$('#create-session-form').submit(submitForm);
}
events();
screenBindings = { 'afterShow': afterShow };
app.bindScreen('session', screenBindings);
this.initialize = function() {
events();
screenBindings = { 'afterShow': afterShow };
app.bindScreen('session', screenBindings);
};
};

View File

@ -2,6 +2,7 @@
context.JK = context.JK || {};
context.JK.FindSessionScreen = function(app) {
var logger = context.JK.logger;
function loadSessions() {
$.ajax({
@ -43,11 +44,13 @@
$('#findSession-tableBody').on("click", '[action="delete"]', deleteSession);
}
screenBindings = {
'afterShow': afterShow
this.initialize = function() {
screenBindings = {
'afterShow': afterShow
};
app.bindScreen('findSession', screenBindings);
events();
};
app.bindScreen('findSession', screenBindings);
events();
};
})(window,jQuery);

View File

@ -5,6 +5,7 @@
var JamKazam = context.JK.JamKazam = function() {
var app;
var logger = context.JK.logger;
function routing() {
var routes = window.RouteMap, rules, rule;

View File

@ -1,52 +0,0 @@
/*
Message builder for communicating over the websocket
*/
(function() {
CLIENT_TARGET = "client"
SERVER_TARGET = "server"
SESSION_TARGET_PREFIX = "session:"
USER_TARGET_PREFIX = "user:"
LOGIN = "LOGIN"
LOGIN_ACK = "LOGIN_ACK"
LOGIN_MUSIC_SESSION = "LOGIN_MUSIC_SESSION"
LOGIN_MUSIC_SESSION_ACK = "LOGIN_MUSIC_SESSION_ACK"
USER_JOINED_MUSIC_SESSION = "USER_JOINED_MUSIC_SESSION"
LEAVE_MUSIC_SESSION = "LEAVE_MUSIC_SESSION"
LEAVE_MUSIC_SESSION_ACK = "LEAVE_MUSIC_SESSION_ACK"
HEARTBEAT = "HEARTBEAT"
TEST_SESSION_MESSAGE = "TEST_SESSION_MESSAGE"
SERVER_GENERIC_ERROR = "SERVER_GENERIC_ERROR"
SERVER_REJECTION_ERROR = "SERVER_REJECTION_ERROR"
var message_factory = {}
function client_container(type, target, inner) {
var type_field = type.toLowerCase()
var body = { "type" : type, "target" : target}
body[type_field] = inner
return body
}
// create a login message using user/pass
message_factory.login_with_user_pass = function(username, password) {
login = { username : username , password : password}
return client_container(LOGIN, SERVER_TARGET, login)
}
// create a login message using token (a cookie or similiar)
message_factory.login_with_token = function(token) {
login = { token : token}
return client_container(LOGIN, SERVER_TARGET, login)
}
// create a music session login message
message_factory.login_music_session = function(music_session) {
login_music_session = { music_session : music_session }
return client_container(LOGIN_MUSIC_SESSION, SERVER_TARGET, login_music_session)
}
window.message_factory = message_factory
})();

View File

@ -0,0 +1,66 @@
/**
* A messaging class for handling websocket messages and taking the
* proper web-ui actions. Anything more generic related to message
* definitions, etc. should be in other places not tied to our UI.
*/
(function(context) {
context.JK = context.JK || {};
context.JK.Messaging = function(app) {
if ("undefined" === typeof(context.JK.JamServer))
return;
// Alias some of the globals for less typing.
var logger = context.JK.logger;
var server = context.JK.JamServer;
var messages = context.JK.MessageType;
var msg_factory = context.JK.MessageFactory;
var myClientId = null;
var myPingTimer = null;
var pingCount = 0;
var maxPings = 5;
function logMessage(messageType, payload) {
logger.debug(messageType + ": " + JSON.stringify(payload));
}
function pingMyself() {
if (!myClientId)
return;
pingCount++;
message = msg_factory.ping(myClientId);
server.send(message);
if (pingCount > maxPings) {
context.clearInterval(myPingTimer);
myPingTimer = null;
}
}
function loggedIn(messageType, payload) {
logger.debug('Logged In handler: ' + messageType + ':' + JSON.stringify(payload));
myClientId = payload.client_id;
myPingTimer = context.setInterval(pingMyself, 1000);
}
function registerLoginPinger() {
logger.debug("registering login -> pinger");
server.registerMessageCallback(messages.LOGIN_ACK, loggedIn);
}
/**
* Register a simple console logger for all known message types.
*/
this.register = function() {
for (var message in messages) {
logger.debug("registering " + message);
server.registerMessageCallback(message, logMessage);
}
registerLoginPinger();
};
};
})(window);

View File

@ -2,6 +2,7 @@
context.JK = context.JK || {};
context.JK.SessionScreen = function(app) {
var logger = context.JK.logger;
function afterShow(data) {
var sessionId = data.id;
@ -35,11 +36,13 @@
$('#session-contents').on("click", '[action="delete"]', deleteSession);
}
events();
screenBindings = {
'afterShow': afterShow
this.initialize = function() {
events();
screenBindings = {
'afterShow': afterShow
};
app.bindScreen('session', screenBindings);
};
app.bindScreen('session', screenBindings);
};

View File

@ -106,7 +106,8 @@
<form id="create-session-form">
<div class="body">
<fieldset class="unstyled">
<legend>Unstyled (obviously)</legend>
<legend>Unstyled and Lots of things omitted</legend>
<!--
<div class="formrow">
<label>Band
<select>
@ -194,12 +195,14 @@
</select>
</label>
</div>
-->
<div class="formrow">
<label>Session Description</label>
<textarea name="description"></textarea>
</div>
<!--
<div class="formrow">
<label>Musician Invitations
<input type="text"/>
@ -227,6 +230,7 @@
I agree that intellectual property ownership of any musical works created during this session shall be governed by the terms of the Creative Commons CC BY-NC-SA license in accordance with the JamKazam Terms of Service.
</label>
</div>
-->
</fieldset>
</div>
<div class="footer">
@ -437,18 +441,30 @@
$(function() {
var jk = JK.JamKazam();
jk.initialize();
new JK.CreateSessionScreen(jk);
new JK.FindSessionScreen(jk);
new JK.SessionScreen(jk);
window.JamServer.registerMessageCallback(
LOGIN_ACK,
function(payload) {
// TODO: Get a list of sessions and update in the UI to enable joining
alert("Logged in from IP: " + payload.public_ip);
var createSessionScreen = new JK.CreateSessionScreen(jk);
createSessionScreen.initialize();
var findSessionScreen = new JK.FindSessionScreen(jk);
findSessionScreen.initialize();
var sessionScreen = new JK.SessionScreen(jk);
sessionScreen.initialize();
var messaging = new JK.Messaging(jk);
messaging.register();
var jam_server = JK.JamServer;
if (jamClient !== undefined) {
jam_server.registerMessageCallback(JK.MessageType.LOGIN_ACK, function(type, payload) {
// This is just a test to kick off sending a few messages to self
// TODO: We need a session first to send p2p messages
//jamClient.JoinSession({ sessionID : 'just a test'});
});
}
window.JamServer.connect();
jam_server.connect();
})
</script>

View File

@ -0,0 +1,16 @@
(function(context, $) {
describe("Logger", function() {
var logger;
beforeEach(function() {
logger = context.JK.logger;
});
it("logger.log present", function() {
logger.log('foo');
});
});
}(window, jQuery));