diff --git a/app/assets/javascripts/jamkazam.js b/app/assets/javascripts/jamkazam.js index 4b60fa0be..65bf97110 100644 --- a/app/assets/javascripts/jamkazam.js +++ b/app/assets/javascripts/jamkazam.js @@ -6,11 +6,17 @@ var JamKazam = context.JK.JamKazam = function() { var app; var logger = context.JK.logger; + var subscribers = {}; // Keys are MessageType.MESSAGE values Values are lists of functions to call + /** + * Dynamically build routes from markup. Any layout="screen" will get a route corresponding to + * his layout-id attribute. If a layout-arg attribute is present, that will be named as a data + * section of the route. + */ function routing() { var routes = window.RouteMap, rules, rule; rules = {}; - context = {}; + routingContext = {}; $('div[layout="screen"]').each(function() { var target = $(this).attr('layout-id'); var targetUrl = target; @@ -22,14 +28,17 @@ app.layout.changeToScreen(target, data); }; rules[target] = {route: '/' + targetUrl, method: target}; - context[target] = fn; + routingContext[target] = fn; }); - routes.context(context); + routes.context(routingContext); for (rule in rules) if (rules.hasOwnProperty(rule)) routes.add(rules[rule]); $(window).bind('hashchange', routes.handler); $(routes.handler); } + /** + * Some simple events for hovering on the home page. May want to move to a separate file. + */ function events() { $('.homecard').on('mouseenter', function() { $(this).addClass('hover'); @@ -39,17 +48,74 @@ }); } + /** + * Handle a websocket message + */ + function handleMessage(header, payload) { + logger.debug(header.type + ": " + JSON.stringify(payload)); + if (header.type in subscribers) { + $.each(subscribers[header.type], function() { + try { + this.call(); + } catch (ex) { + logger.warn(ex); + } + }); + } + } + /** + * Register for all known types, logging events as they happen, and + * notifying subscribers (see this.subscribe) as they occur. + */ + function _registerMessages() { + for (var message in context.JK.MessageType) { + logger.debug("registering " + message); + context.JK.JamServer.registerMessageCallback(message, handleMessage); + } + } + + /** + * Provide a function to call when a certain event type happens. + * No checks for dupes here, so take care to not add the same handler + * for the same event type repeatedly. + * Event Types should be one of the values in JK.MessageType + */ + this.subscribe = function(eventType, handler) { + if (!(eventType in subscribers)) { + subscribers[eventType] = []; + } + subscribers[eventType].push(handler); + }; + + /** + * Expose event firing. Generally not to be used except by tests. + */ + this.fireEvent = handleMessage; + + /** + * Provide a handler object for events related to a particular screen + * being shown or hidden. + * @screen is a string corresponding to the screen's layout-id attribute + * @handler is an object with up to four optional keys: + * beforeHide, afterHide, beforeShow, afterShow, which should all have + * functions as values. If there is data provided by the screen's route + * it will be provided to these functions. + */ this.bindScreen = function(screen, handler) { this.layout.bindScreen(screen, handler); }; + /** + * Two-phase construction. Call after construction when in non-unit-test use. + */ this.initialize = function() { var url, hash; app = this; this.layout = new JK.Layout(); this.layout.initialize(); routing(); + _registerMessages(); events(); hash = location.hash; diff --git a/app/assets/javascripts/messaging.js b/app/assets/javascripts/messaging.js index b540d596d..6b4bb47fb 100644 --- a/app/assets/javascripts/messaging.js +++ b/app/assets/javascripts/messaging.js @@ -53,14 +53,9 @@ * 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); \ No newline at end of file +})(window); \ No newline at end of file diff --git a/app/assets/javascripts/session.js b/app/assets/javascripts/session.js index 6e0b7c39d..63e97b096 100644 --- a/app/assets/javascripts/session.js +++ b/app/assets/javascripts/session.js @@ -13,11 +13,39 @@ } function renderSession(sessionData) { - $contents = $('#session-contents'); - $contents.empty(); + _renderSessionInfo(sessionData); + // TODO: Just for testing. Should respond to events. + var trackData = { + clientId: 1, + name: "Jonathon Wilson", + part: "Keyboard", + avatar: "https://en.gravatar.com/userimage/3198431/5ba95e655ce68d976f46dcf6f99fdde5.png", + latency: "good", + vu: 0.0, + gain: 0.5, + mute: false + }; + _addTrack(trackData); + // TODO - hook events to the session-tracks container, not the tracks. + // then have the events see which track fired. + } + + function _renderSessionInfo(sessionData) { + $info = $('#session-info'); + $info.empty(); var template = $('#template-session-contents').html(); var contents = JK.fillTemplate(template, sessionData); - $contents.html(contents); + $info.html(contents); + } + + function _addTrack(trackData) { + var template = $('#template-session-track').html(); + var newTrack = JK.fillTemplate(template, trackData); + $('#session-tracks').append(newTrack); + } + + function _userJoinedSession() { + logger.debug(arguments); } function deleteSession(evt) { @@ -42,6 +70,7 @@ 'afterShow': afterShow }; app.bindScreen('session', screenBindings); + app.subscribe(JK.MessageType.USER_JOINED_MUSIC_SESSION, _userJoinedSession); }; }; diff --git a/app/assets/javascripts/sessionTrack.js b/app/assets/javascripts/sessionTrack.js new file mode 100644 index 000000000..8117fcf14 --- /dev/null +++ b/app/assets/javascripts/sessionTrack.js @@ -0,0 +1,81 @@ +(function(context,$) { + + context.JK = context.JK || {}; + context.JK.SessionTrack = function() { + var logger = context.JK.logger; + + function events() { + $('#session-contents').on("click", '[action="delete"]', deleteSession); + } + + /** + * Set latency. val = [good,medium,bad] + */ + function _setLatency(val) { + } + + /** + * Set VU level. val = 0.0-1.0 + */ + function _setVolumeUnit(val) { + } + + /** + * Set the track's gain. val = 0.0-1.0 + * Allows external control of channel fader. + */ + function _setGain(val) { + } + + /** + * Get the track's gain from current fader. Returns 0.0-1.0 + */ + function _getGain() { + } + + /** + * Set whether this channel is muted. Takes a boolean where + * true means mute, false, means unmuted. + */ + function _mute(muted) { + } + + /** + * Return whether the channel is currently muted. + */ + function _isMute() { + } + + /** + * Set the name (typically user name) + */ + function _setName(name) { + } + + /** + * Set the part this user is performing. If part is + * one of ENUM.FIGURE_ME_OUT then it is a recognized + * part with an icon, otherwise it is an 'other' value + * with a default icon. + */ + function _setPart(part) { + } + + /** + * Set the channel's avatar. Typically the user's profile + * avatar url. + */ + function _setAvatar(avatar_url) { + } + + this.initialize = function() { + events(); + screenBindings = { + 'afterShow': afterShow + }; + app.bindScreen('session', screenBindings); + }; + + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/views/clients/index.html.erb b/app/views/clients/index.html.erb index 9739fd67b..2adf86196 100644 --- a/app/views/clients/index.html.erb +++ b/app/views/clients/index.html.erb @@ -371,6 +371,8 @@
Session