Merge branch 'master' of bitbucket.org:jamkazam/jam-web
This commit is contained in:
commit
a47349f4c8
|
|
@ -18,6 +18,7 @@
|
|||
LEAVE_MUSIC_SESSION : "LEAVE_MUSIC_SESSION",
|
||||
LEAVE_MUSIC_SESSION_ACK : "LEAVE_MUSIC_SESSION_ACK",
|
||||
HEARTBEAT : "HEARTBEAT",
|
||||
HEARTBEAT_ACK : "HEARTBEAT_ACK",
|
||||
FRIEND_UPDATE : "FRIEND_UPDATE",
|
||||
SESSION_INVITATION : "SESSION_INVITATION",
|
||||
JOIN_REQUEST : "JOIN_REQUEST",
|
||||
|
|
|
|||
|
|
@ -52,6 +52,15 @@
|
|||
server.socket.onclose = server.onClose;
|
||||
};
|
||||
|
||||
server.close = function(in_error) {
|
||||
logger.log("closing websocket");
|
||||
|
||||
server.socket.close();
|
||||
|
||||
if(in_error) {
|
||||
context.JK.CurrentSessionModel.onWebsocketDisconnected();
|
||||
}
|
||||
}
|
||||
server.rememberLogin = function() {
|
||||
var token, loginMessage;
|
||||
token = $.cookie("remember_token");
|
||||
|
|
@ -95,7 +104,8 @@
|
|||
context.jamClient.connected = false;
|
||||
}
|
||||
|
||||
// TODO: reconnect
|
||||
context.JK.CurrentSessionModel.onWebsocketDisconnected();
|
||||
|
||||
};
|
||||
|
||||
server.send = function(message) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
(function(context,$) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.Banner = (function() {
|
||||
var self = this;
|
||||
var logger = context.JK.logger;
|
||||
|
||||
// responsible for updating the contents of the update dialog
|
||||
// as well as registering for any event handlers
|
||||
function show(options) {
|
||||
var text = options.text;
|
||||
var html = options.html;
|
||||
|
||||
var newContent = null;
|
||||
if (html) {
|
||||
newContent = $('#banner .dialog-inner').html(html);
|
||||
}
|
||||
else if(text) {
|
||||
newContent = $('#banner .dialog-inner').html(text);
|
||||
}
|
||||
else {
|
||||
console.error("unable to show banner for empty message")
|
||||
return newContent;
|
||||
}
|
||||
|
||||
$('#banner').show()
|
||||
$('#banner_overlay').show()
|
||||
|
||||
// return the core of the banner so that caller can attach event handlers to newly created HTML
|
||||
return newContent;
|
||||
}
|
||||
|
||||
function hide() {
|
||||
$('#banner').hide();
|
||||
$('#banner_overlay .dialog-inner').html("");
|
||||
$('#banner_overlay').hide();
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Expose publics
|
||||
var me = {
|
||||
initialize: initialize,
|
||||
show : show,
|
||||
hide : hide
|
||||
}
|
||||
|
||||
return me;
|
||||
})();
|
||||
|
||||
})(window,jQuery);
|
||||
|
|
@ -76,6 +76,10 @@
|
|||
function settingsInit() {
|
||||
jamClient.FTUEInit();
|
||||
setLevels(0);
|
||||
// Always reset the driver select box to "Choose..." which forces everything
|
||||
// to sync properly when the user reselects their driver of choice.
|
||||
// VRFS-375 and VRFS-561
|
||||
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .asio-settings .settings-driver select').val("");
|
||||
}
|
||||
|
||||
function setLevels(db) {
|
||||
|
|
@ -266,7 +270,29 @@
|
|||
ftueSave(false);
|
||||
}
|
||||
|
||||
function videoLinkClicked(evt) {
|
||||
var myOS = jamClient.GetOSAsString();
|
||||
var link;
|
||||
if (myOS === 'MacOSX') {
|
||||
link = $(evt.currentTarget).attr('external-link-mac');
|
||||
} else if (myOS === 'Win32') {
|
||||
link = $(evt.currentTarget).attr('external-link-win');
|
||||
}
|
||||
if (link) {
|
||||
context.jamClient.OpenSystemBrowser(link);
|
||||
}
|
||||
}
|
||||
|
||||
function events() {
|
||||
$('.ftue-video-link').hover(
|
||||
function(evt) { // handlerIn
|
||||
$(this).addClass('hover');
|
||||
},
|
||||
function(evt) { // handlerOut
|
||||
$(this).removeClass('hover');
|
||||
}
|
||||
);
|
||||
$('.ftue-video-link').on('click', videoLinkClicked);
|
||||
$('[layout-wizard-step="2"] .settings-driver select').on('change', audioDriverChanged);
|
||||
$('[layout-wizard-step="2"] .settings-controls select').on('change', audioDeviceChanged);
|
||||
$('#btn-asio-control-panel').on('click', openASIOControlPanel);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
/** check if the server is alive */
|
||||
function serverHealthCheck(options) {
|
||||
return $.ajax({
|
||||
url: window.host,
|
||||
cache: false,
|
||||
dataType: "html"
|
||||
});
|
||||
}
|
||||
|
||||
function getId(options) {
|
||||
var id = options && options["id"]
|
||||
|
||||
|
|
@ -201,6 +210,7 @@
|
|||
this.getClientDownloads = getClientDownloads
|
||||
this.createInvitation = createInvitation;
|
||||
this.postFeedback = postFeedback;
|
||||
this.serverHealthCheck = serverHealthCheck;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
var app;
|
||||
var logger = context.JK.logger;
|
||||
var heartbeatInterval=null;
|
||||
var heartbeatMS=null;
|
||||
var inBadState=false;
|
||||
var lastHeartbeatAckTime=null;
|
||||
|
||||
var opts = {
|
||||
layoutOpts: {}
|
||||
|
|
@ -59,6 +61,15 @@
|
|||
if (app.heartbeatActive) {
|
||||
var message = context.JK.MessageFactory.heartbeat();
|
||||
context.JK.JamServer.send(message);
|
||||
|
||||
// check if the server is still sending heartbeat acks back down
|
||||
// this logic equates to 'if we have not received a heartbeat within 2 heartbeat intervals, then get upset
|
||||
if(new Date().getTime() - lastHeartbeatAckTime.getTime() > heartbeatMS * 2) {
|
||||
logger.error("no heartbeat ack received from server after twice heartbeat interval. giving up");
|
||||
clearInterval(heartbeatInterval); // stop future heartbeats
|
||||
context.JK.JamServer.close(true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,9 +78,14 @@
|
|||
$.cookie('client_id', payload.client_id);
|
||||
// $.cookie('remember_token', payload.token); // removed per vrfs-273/403
|
||||
|
||||
var heartbeatMS = payload.heartbeat_interval * 1000;
|
||||
heartbeatMS = payload.heartbeat_interval * 1000;
|
||||
logger.debug("jamkazam.js.loggedIn(): clientId now " + app.clientId + "; Setting up heartbeat every " + heartbeatMS + " MS");
|
||||
heartbeatInterval = context.setInterval(_heartbeat, heartbeatMS);
|
||||
lastHeartbeatAckTime = new Date(new Date().getTime() + heartbeatMS); // add a little forgiveness to server for initial heartbeat
|
||||
}
|
||||
|
||||
function heartbeatAck(header, payload) {
|
||||
lastHeartbeatAckTime = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,6 +115,12 @@
|
|||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.LOGIN_ACK, loggedIn);
|
||||
}
|
||||
|
||||
function registerHeartbeatAck() {
|
||||
logger.debug("register for heartbeatAck");
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, heartbeatAck);
|
||||
}
|
||||
|
||||
|
||||
function registerBadStateError() {
|
||||
logger.debug("register for server_bad_state_error");
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SERVER_BAD_STATE_ERROR, serverBadStateError);
|
||||
|
|
@ -218,6 +240,7 @@
|
|||
this.layout = new context.JK.Layout();
|
||||
this.layout.initialize(this.opts.layoutOpts);
|
||||
registerLoginAck();
|
||||
registerHeartbeatAck();
|
||||
registerBadStateRecovered();
|
||||
registerBadStateError();
|
||||
events();
|
||||
|
|
|
|||
|
|
@ -121,22 +121,37 @@
|
|||
}
|
||||
|
||||
function afterCurrentUserLoaded() {
|
||||
sessionModel = new context.JK.SessionModel(
|
||||
// It seems the SessionModel should be a singleton.
|
||||
// a client can only be in one session at a time,
|
||||
// and other parts of the code want to know at any certain times
|
||||
// about the current session, if any (for example, reconnect logic)
|
||||
context.JK.CurrentSessionModel = sessionModel = new context.JK.SessionModel(
|
||||
context.JK.JamServer,
|
||||
context.jamClient,
|
||||
context.JK.userMe
|
||||
context.jamClient
|
||||
);
|
||||
|
||||
sessionModel.subscribe('sessionScreen', sessionChanged);
|
||||
sessionModel.joinSession(sessionId);
|
||||
sessionModel.joinSession(sessionId)
|
||||
.fail(function(xhr, textStatus, errorMessage) {
|
||||
if(xhr.status == 404) {
|
||||
// we tried to join the session, but it's already gone. kick user back to join session screen
|
||||
window.location = "#/findSession"
|
||||
app.notify(
|
||||
{ title: "Unable to Join Session",
|
||||
text: "The session you attempted to join is over."
|
||||
},
|
||||
{ no_cancel: true });
|
||||
}else {
|
||||
app.ajaxError(xhr, textStatus, errorMessage);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function beforeHide(data) {
|
||||
// track that the screen is inactive, to disable body-level handlers
|
||||
screenActive = false;
|
||||
sessionModel.leaveCurrentSession(sessionId);
|
||||
// 'unregister' for callbacks
|
||||
context.jamClient.SessionRegisterCallback("");
|
||||
context.jamClient.SessionSetAlertCallback("");
|
||||
sessionModel.leaveCurrentSession()
|
||||
.fail(app.ajaxError)
|
||||
}
|
||||
|
||||
function sessionChanged() {
|
||||
|
|
@ -364,7 +379,6 @@
|
|||
]);
|
||||
if (mixer) {
|
||||
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
|
||||
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
var muteClass = "enabled";
|
||||
|
|
@ -412,6 +426,25 @@
|
|||
});
|
||||
}
|
||||
|
||||
function connectTrackToMixer(trackSelector, clientId, mixerId, gainPercent) {
|
||||
var vuOpts = $.extend({}, trackVuOpts);
|
||||
var faderOpts = $.extend({}, trackFaderOpts);
|
||||
faderOpts.faderId = mixerId;
|
||||
var vuLeftSelector = trackSelector + " .track-vu-left";
|
||||
var vuRightSelector = trackSelector + " .track-vu-right";
|
||||
var faderSelector = trackSelector + " .track-gain";
|
||||
var $track = $('div.track[client-id="' + clientId + '"]');
|
||||
// Set mixer-id attributes and render VU/Fader
|
||||
context.JK.VuHelpers.renderVU(vuLeftSelector, vuOpts);
|
||||
$track.find('.track-vu-left').attr('mixer-id', mixerId + '_vul');
|
||||
context.JK.VuHelpers.renderVU(vuRightSelector, vuOpts);
|
||||
$track.find('.track-vu-right').attr('mixer-id', mixerId + '_vur');
|
||||
context.JK.FaderHelpers.renderFader(faderSelector, faderOpts);
|
||||
// Set gain position
|
||||
context.JK.FaderHelpers.setFaderValue(mixerId, gainPercent);
|
||||
context.JK.FaderHelpers.subscribe(mixerId, faderChanged);
|
||||
}
|
||||
|
||||
// Function called on an interval when participants change. Mixers seem to
|
||||
// show up later, so we render the tracks from participants, but keep track
|
||||
// of the ones there weren't any mixers for, and continually try to find them
|
||||
|
|
@ -428,32 +461,14 @@
|
|||
ChannelGroupIds.PeerAudioInputMusicGroup
|
||||
]);
|
||||
if (mixer) {
|
||||
var vuOpts = $.extend({}, trackVuOpts);
|
||||
var faderOpts = $.extend({}, trackFaderOpts);
|
||||
faderOpts.faderId = mixer.id;
|
||||
var baseSelector = 'div.track[client-id="' + key + '"]';
|
||||
var vuLeftSelector = baseSelector + " .track-vu-left";
|
||||
var vuRightSelector = baseSelector + " .track-vu-right";
|
||||
var faderSelector = baseSelector + " .track-gain";
|
||||
|
||||
keysToDelete.push(key);
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
var trackSelector = 'div.track[client-id="' + key + '"]';
|
||||
connectTrackToMixer(trackSelector, key, mixer.id, gainPercent);
|
||||
var $track = $('div.track[client-id="' + key + '"]');
|
||||
// Set mixer-id attributes and render VU/Fader
|
||||
context.JK.VuHelpers.renderVU(vuLeftSelector, vuOpts);
|
||||
$track.find('.track-vu-left').attr('mixer-id', mixer.id + '_vul');
|
||||
context.JK.VuHelpers.renderVU(vuRightSelector, vuOpts);
|
||||
$track.find('.track-vu-right').attr('mixer-id', mixer.id + '_vur');
|
||||
context.JK.FaderHelpers.renderFader(faderSelector, faderOpts);
|
||||
context.JK.FaderHelpers.subscribe(mixer.id, faderChanged);
|
||||
|
||||
$track.find('.track-icon-mute').attr('mixer-id', mixer.id);
|
||||
$track.find('.track-icon-settings').attr('mixer-id', mixer.id);
|
||||
|
||||
// Set gain position
|
||||
context.JK.FaderHelpers.setFaderValue(mixer.id, gainPercent);
|
||||
|
||||
// Set mute state
|
||||
_toggleVisualMuteControl($track.find('.track-icon-mute'), mixer.mute);
|
||||
}
|
||||
|
|
@ -513,25 +528,9 @@
|
|||
$destination.append(newTrack);
|
||||
|
||||
// Render VU meters and gain fader
|
||||
// Find the last child (just-appended):
|
||||
var trackCount = $(parentSelector + ' .session-track').length;
|
||||
var selectorPrefix = parentSelector + ' .session-track:nth-child(' + String(trackCount) + ')';
|
||||
var vuOpts = $.extend({}, trackVuOpts);
|
||||
var faderOpts = $.extend({}, trackFaderOpts);
|
||||
faderOpts.faderId = trackData.mixerId;
|
||||
var vuLeftSelector = selectorPrefix + ' .track-vu-left';
|
||||
var vuRightSelector = selectorPrefix + ' .track-vu-right';
|
||||
var faderSelector = selectorPrefix + ' .track-gain';
|
||||
context.JK.VuHelpers.renderVU(vuLeftSelector, vuOpts);
|
||||
context.JK.VuHelpers.renderVU(vuRightSelector, vuOpts);
|
||||
context.JK.FaderHelpers.renderFader(faderSelector, faderOpts);
|
||||
context.JK.FaderHelpers.subscribe(trackData.mixerId, faderChanged);
|
||||
// Visually update fader to underlying mixer start value.
|
||||
if (trackData.gainPercent) {
|
||||
context.JK.FaderHelpers.setFaderValue(trackData.mixerId, trackData.gainPercent);
|
||||
} else {
|
||||
context.JK.FaderHelpers.setFaderValue(trackData.mixerId, 0);
|
||||
}
|
||||
var trackSelector = parentSelector + ' .session-track[client-id="' + trackData.clientId + '"]';
|
||||
var gainPercent = trackData.gainPercent || 0;
|
||||
connectTrackToMixer(trackSelector, trackData.clientId, trackData.mixerId, gainPercent);
|
||||
|
||||
var $closeButton = $('#div-track-close', 'div[track-id="' + trackData.trackId + '"]');
|
||||
if (index === 0) {
|
||||
|
|
@ -564,11 +563,12 @@
|
|||
|
||||
function handleVolumeChangeCallback(mixerId, isLeft, value) {
|
||||
// Visually update mixer
|
||||
// There is no need to actually set the back-end mixer value as the
|
||||
// back-end will already have updated the audio mixer directly prior to sending
|
||||
// me this event. I simply need to visually show the new fader position.
|
||||
// TODO: Use mixer's range
|
||||
var faderValue = percentFromMixerValue(-80, 20, value);
|
||||
context.JK.FaderHelpers.setFaderValue(mixerId, faderValue);
|
||||
fillTrackVolumeObject(mixerId, false); // don't broadcast
|
||||
setMixerVolume(mixerId, faderValue);
|
||||
}
|
||||
|
||||
function handleBridgeCallback() {
|
||||
|
|
@ -593,6 +593,8 @@
|
|||
}
|
||||
_updateVU(mixerId, vuVal);
|
||||
} else if (eventName === 'add' || eventName === 'remove') {
|
||||
//logger.dbg('non-vu event: ' + eventName + ',' + mixerId + ',' + value);
|
||||
|
||||
// TODO - _renderSession. Note I get streams of these in
|
||||
// sequence, so have Nat fix, or buffer/spam protect
|
||||
// Note - this is already handled from websocket events.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
context.JK = context.JK || {};
|
||||
var logger = context.JK.logger;
|
||||
|
||||
context.JK.SessionModel = function(server, client, currentUser) {
|
||||
context.JK.SessionModel = function(server, client) {
|
||||
var clientId = client.clientID;
|
||||
var currentSessionId = null; // Set on join, prior to setting currentSession.
|
||||
var currentSession = null;
|
||||
var subscribers = {};
|
||||
var users = {}; // User info for session participants
|
||||
var rest = context.JK.Rest();
|
||||
|
||||
function id() {
|
||||
return currentSession.id;
|
||||
|
|
@ -32,24 +33,54 @@
|
|||
function joinSession(sessionId) {
|
||||
currentSessionId = sessionId;
|
||||
logger.debug("SessionModel.joinSession(" + sessionId + ")");
|
||||
joinSessionRest(sessionId, function() {
|
||||
refreshCurrentSession();
|
||||
});
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession);
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession);
|
||||
var deferred = joinSessionRest(sessionId);
|
||||
|
||||
deferred
|
||||
.done(function(){
|
||||
logger.debug("calling jamClient.JoinSession");
|
||||
client.JoinSession({ sessionID: sessionId });
|
||||
refreshCurrentSession();
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession);
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession);
|
||||
});
|
||||
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave the current session
|
||||
* Leave the current session, if there is one.
|
||||
* callback: called in all conditions; either after an attempt is made to tell the server that we are leaving,
|
||||
* or immediately if there is no session
|
||||
*/
|
||||
function leaveCurrentSession() {
|
||||
logger.debug("SessionModel.leaveCurrentSession()");
|
||||
// TODO - sessionChanged will be called with currentSession = null
|
||||
server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession);
|
||||
server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession);
|
||||
leaveSessionRest(currentSessionId, sessionChanged);
|
||||
currentSession = null;
|
||||
currentSessionId = null;
|
||||
var deferred;
|
||||
|
||||
if(currentSessionId) {
|
||||
logger.debug("SessionModel.leaveCurrentSession()");
|
||||
// TODO - sessionChanged will be called with currentSession = null
|
||||
server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession);
|
||||
server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession);
|
||||
// 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("calling jamClient.LeaveSession for clientId=" + clientId);
|
||||
client.LeaveSession({ sessionID: currentSessionId });
|
||||
deferred = leaveSessionRest(currentSessionId);
|
||||
deferred.done(function() {
|
||||
sessionChanged();
|
||||
});
|
||||
|
||||
// 'unregister' for callbacks
|
||||
context.jamClient.SessionRegisterCallback("");
|
||||
context.jamClient.SessionSetAlertCallback("");
|
||||
currentSession = null;
|
||||
currentSessionId = null;
|
||||
}
|
||||
else {
|
||||
deferred = rest.serverHealthCheck();
|
||||
}
|
||||
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -268,7 +299,7 @@
|
|||
* Make the server calls to join the current user to
|
||||
* the session provided.
|
||||
*/
|
||||
function joinSessionRest(sessionId, callback) {
|
||||
function joinSessionRest(sessionId) {
|
||||
var tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
|
||||
var data = {
|
||||
client_id: clientId,
|
||||
|
|
@ -277,38 +308,77 @@
|
|||
tracks: tracks
|
||||
};
|
||||
var url = "/api/sessions/" + sessionId + "/participants";
|
||||
$.ajax({
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: url,
|
||||
async: false,
|
||||
data: JSON.stringify(data),
|
||||
processData:false,
|
||||
success: function(response) {
|
||||
logger.debug("calling jamClient.JoinSession");
|
||||
client.JoinSession({ sessionID: sessionId });
|
||||
callback();
|
||||
},
|
||||
error: ajaxError
|
||||
processData:false
|
||||
});
|
||||
}
|
||||
|
||||
function leaveSessionRest(sessionId, callback) {
|
||||
function leaveSessionRest(sessionId) {
|
||||
var url = "/api/participants/" + clientId;
|
||||
$.ajax({
|
||||
return $.ajax({
|
||||
type: "DELETE",
|
||||
url: url,
|
||||
async: false,
|
||||
success: function (response) {
|
||||
logger.debug("calling jamClient.LeaveSession for clientId=" + clientId);
|
||||
client.LeaveSession({ sessionID: sessionId });
|
||||
callback();
|
||||
},
|
||||
error: ajaxError
|
||||
async: false
|
||||
});
|
||||
}
|
||||
|
||||
function reconnect() {
|
||||
window.location.reload();
|
||||
}
|
||||
function registerReconnect(content) {
|
||||
$('a.disconnected-reconnect', content).click(function() {
|
||||
|
||||
var template = $('#template-reconnecting').html();
|
||||
var templateHtml = context.JK.fillTemplate(template, null);
|
||||
var content = context.JK.Banner.show({
|
||||
html : template
|
||||
});
|
||||
|
||||
context.JK.CurrentSessionModel.leaveCurrentSession()
|
||||
.done(function() {
|
||||
reconnect();
|
||||
})
|
||||
.fail(function(xhr, textStatus, errorThrown) {
|
||||
console.log("leaveCurrentSession failed: ", arguments);
|
||||
|
||||
if(xhr && xhr.status >= 100) {
|
||||
// we could connect to the server, and it's alive
|
||||
reconnect();
|
||||
}
|
||||
else {
|
||||
var template = $('#template-could-not-reconnect').html();
|
||||
var templateHtml = context.JK.fillTemplate(template, null);
|
||||
var content = context.JK.Banner.show({
|
||||
html : template
|
||||
});
|
||||
|
||||
registerReconnect(content);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function onWebsocketDisconnected() {
|
||||
var template = $('#template-disconnected').html();
|
||||
var templateHtml = context.JK.fillTemplate(template, null);
|
||||
var content = context.JK.Banner.show({
|
||||
html : template
|
||||
}) ;
|
||||
|
||||
// kill the streaming of the session immediately
|
||||
logger.debug("calling jamClient.LeaveSession for clientId=" + clientId);
|
||||
client.LeaveSession({ sessionID: currentSessionId });
|
||||
|
||||
registerReconnect(content);
|
||||
}
|
||||
|
||||
function ajaxError(jqXHR, textStatus, errorMessage) {
|
||||
logger.error("Unexpected ajax error: " + textStatus);
|
||||
}
|
||||
|
|
@ -324,6 +394,7 @@
|
|||
this.addTrack = addTrack;
|
||||
this.updateTrack = updateTrack;
|
||||
this.deleteTrack = deleteTrack;
|
||||
this.onWebsocketDisconnected = onWebsocketDisconnected;
|
||||
this.getCurrentSession = function() {
|
||||
return currentSession;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -147,12 +147,16 @@
|
|||
});
|
||||
}
|
||||
|
||||
context.JK.trimString = function(str) {
|
||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
};
|
||||
|
||||
context.JK.padString = function(str, max) {
|
||||
var retVal = '' + str;
|
||||
while (retVal.length < max) {
|
||||
retVal = '0' + retVal;
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
#banner {
|
||||
display:none;
|
||||
}
|
||||
|
||||
#banner h2 {
|
||||
font-weight:bold;
|
||||
font-size:x-large;
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
*= require ./genreSelector
|
||||
*= require ./sessionList
|
||||
*= require ./searchResults
|
||||
*= require ./banner
|
||||
*= require ./clientUpdate
|
||||
*= require jquery.Jcrop
|
||||
*/
|
||||
|
|
@ -18,12 +18,16 @@ div.dialog.ftue .ftue-inner div[layout-wizard-step="1"] {
|
|||
|
||||
li {
|
||||
text-align:center;
|
||||
width: 33%;
|
||||
width: 31%;
|
||||
height: 170px;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
/*padding:0px;*/
|
||||
list-style: none;
|
||||
float:left;
|
||||
}
|
||||
li.first {
|
||||
width: 34%;
|
||||
}
|
||||
}
|
||||
div.dialog.ftue .ftue-inner div[layout-wizard-step="3"] {
|
||||
h5 {
|
||||
|
|
@ -421,3 +425,14 @@ table.audiogeartable {
|
|||
font-size:15px;
|
||||
color:#aaa;
|
||||
}
|
||||
|
||||
.ftue-video-link {
|
||||
padding:4px;
|
||||
cursor:pointer;
|
||||
background-color:#333;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
.ftue-video-link.hover {
|
||||
background-color:#444;
|
||||
border: 1px solid #555;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,22 +53,23 @@ class ApiUsersController < ApiController
|
|||
end
|
||||
|
||||
def update
|
||||
@user = User.save(params[:id],
|
||||
current_user.id,
|
||||
params[:first_name],
|
||||
params[:last_name],
|
||||
nil, # Don't allow changing email here, since updating email is something that must be done through it's own API
|
||||
nil, # Don't allow changing password here, since we want to prompt again for the old password
|
||||
nil,
|
||||
params[:musician],
|
||||
params[:gender],
|
||||
params[:birth_date],
|
||||
params[:internet_service_provider],
|
||||
params[:city],
|
||||
params[:state],
|
||||
params[:country],
|
||||
params[:instruments].nil? ? [] : params[:instruments], # we have to convert nil to empty []. background: http://stackoverflow.com/questions/14647731/rails-converts-empty-arrays-into-nils-in-params-of-the-request
|
||||
params[:photo_url])
|
||||
|
||||
@user = User.find(params[:id])
|
||||
|
||||
|
||||
@user.first_name = params[:first_name] if params.has_key?(:first_name)
|
||||
@user.last_name = params[:last_name] if params.has_key?(:last_name)
|
||||
@user.gender = params[:gender] if params.has_key?(:gender)
|
||||
@user.birth_date = Date.strptime(params[:birth_date], '%m-%d-%Y') if params.has_key?(:birth_date)
|
||||
@user.city = params[:city] if params.has_key?(:city)
|
||||
@user.state = params[:state] if params.has_key?(:state)
|
||||
@user.country = params[:country] if params.has_key?(:country)
|
||||
@user.musician = params[:musician] if params.has_key?(:musician)
|
||||
@user.update_instruments(params[:instruments].nil? ? [] : params[:instruments]) if params.has_key?(:instruments)
|
||||
|
||||
puts params[:birth_date]
|
||||
@user.save
|
||||
puts @user.birth_date.inspect
|
||||
|
||||
if @user.errors.any?
|
||||
respond_with @user, :status => :unprocessable_entity
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
module MetaHelper
|
||||
|
||||
def version()
|
||||
"web=#{::JamWeb::VERSION} lib=#{JamRuby::VERSION} db=#{JamDb::VERSION} pb=#{Jampb::VERSION}"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
<td valign="top">
|
||||
<div class="field">
|
||||
Gender:<br />
|
||||
<select name="gender" data-value="{gender}" class="w80"><option value='M'>Male</option><option value='F'>Female</option><option value="">-</option></select><br />
|
||||
<select name="gender" data-value="{gender}" class="w80"><option value='M'>Male</option><option value='F'>Female</option><option >-</option></select><br />
|
||||
<br />
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
<!-- generic banner for use by an code -->
|
||||
<div class="overlay" id="banner_overlay"></div>
|
||||
<div id="banner" class="dialog-overlay-sm">
|
||||
|
||||
<!-- dialog header -->
|
||||
<div class="content-head">
|
||||
<%= image_tag("content/icon_alert.png", :height => '24', :width => '24', :class => "content-icon") %><h1>alert</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="dialog-inner">
|
||||
<!-- contents are replaced by caller to f-->
|
||||
</div>
|
||||
<!-- end right column -->
|
||||
<br clear="all">
|
||||
|
||||
</div>
|
||||
|
|
@ -10,35 +10,37 @@
|
|||
<!-- First screen of the FTUE wizard -->
|
||||
<div layout-wizard-step="1" dialog-title="welcome!" style="display:block;">
|
||||
<p class="intro">
|
||||
Please identify which of the three types of audio gear below you are going to use with the JamKazam
|
||||
service, and click either the Windows or Mac link under the appropriate gear to watch a video on how
|
||||
to navigate this initial setup and testing process. After watching the video, click the 'NEXT'
|
||||
button to get started.
|
||||
Please identify which of the three types of audio gear below you
|
||||
are going to use with the JamKazam service, and click one to
|
||||
watch a video on how to navigate this initial setup and testing
|
||||
process. After watching the video, click the 'NEXT' button to
|
||||
get started. If you don't have your audio gear handy now, click
|
||||
Cancel.
|
||||
</p>
|
||||
|
||||
<ul class="device_type">
|
||||
<li>
|
||||
<li class="ftue-video-link first"
|
||||
external-link-win="http://www.youtube.com/watch?v=b1JrwGeUcOo"
|
||||
external-link-mac="http://www.youtube.com/watch?v=TRzb7OTlO-Q">
|
||||
AUDIO DEVICE WITH PORTS FOR INSTRUMENT OR MIC INPUT JACKS<br/>
|
||||
<p><%= image_tag "content/audio_capture_ftue.png", {:width => 243, :height => 70} %></p>
|
||||
<p><a href="http://www.youtube.com/watch?v=jM5_MWtlxxE" rel="external">Windows Video</a><br/>
|
||||
<a href="http://www.youtube.com/watch?v=TRzb7OTlO-Q" rel="external">Mac Video</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<li class="ftue-video-link"
|
||||
external-link-win="http://www.youtube.com/watch?v=IDrLa8TOXwQ"
|
||||
external-link-mac="http://www.youtube.com/watch?v=vIs7ArrjMpE">
|
||||
USB MICROPHONE<br/>
|
||||
<p><%= image_tag "content/microphone_ftue.png", {:width => 70, :height => 113} %></p>
|
||||
<p><a href="http://www.youtube.com/watch?v=IDrLa8TOXwQ" rel="external">Windows Video</a><br/>
|
||||
<a href="http://www.youtube.com/watch?v=vIs7ArrjMpE" rel="external">Mac Video</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<li class="ftue-video-link"
|
||||
external-link-win="http://www.youtube.com/watch?v=PCri4Xed4CA"
|
||||
external-link-mac="http://www.youtube.com/watch?v=Gatmd_ja47U">
|
||||
COMPUTER'S BUILT-IN MIC & SPEAKERS/HEADPHONES<br/>
|
||||
<p><%= image_tag "content/computer_ftue.png", {:width => 118, :height => 105} %></p>
|
||||
<p><a href="http://www.youtube.com/watch?v=PCri4Xed4CA" rel="external">Windows Video</a><br/>
|
||||
<a href="http://www.youtube.com/watch?v=Gatmd_ja47U" rel="external">Mac Video</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="right mr30 buttonbar">
|
||||
<!-- <a class="button-grey" layout-action="close">REGISTER AS A FAN</a> -->
|
||||
<a class="button-grey" layout-action="close">CANCEL</a>
|
||||
<a class="button-orange" layout-wizard-link="2">NEXT</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<script type="text/template" id="template-disconnected">
|
||||
<h2 align="center">Disconnected from Server</h2>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div align="center">
|
||||
You have been disconnected from JamKazam.
|
||||
</div>
|
||||
<br clear="all" /><br />
|
||||
|
||||
<div class="right">
|
||||
<a href="#" class="button-orange disconnected-reconnect">RECONNECT</a>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-reconnecting">
|
||||
<h2 align="center">Reconnecting to Server</h2>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div align="center">
|
||||
Attempting to reestablish connection to the server...
|
||||
</div>
|
||||
<br clear="all" /><br />
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-could-not-reconnect">
|
||||
<h2 align="center">Unable to Reconnect</h2>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div align="center">
|
||||
We were not able to reconnect to JamKazam. <br/></br/>
|
||||
Please check your internet connection, then try again later.
|
||||
</div>
|
||||
<br clear="all" /><br />
|
||||
<div class="right">
|
||||
<a href="#" class="button-orange disconnected-reconnect">TRY AGAIN TO RECONNECT</a>
|
||||
</div>
|
||||
</script>
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
<%= render "account_audio_profile" %>
|
||||
<%= render "notify" %>
|
||||
<%= render "client_update" %>
|
||||
<%= render "banner" %>
|
||||
<%= render "clients/banners/disconnected" %>
|
||||
<%= render "overlay_small" %>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
@ -82,6 +84,8 @@
|
|||
var clientUpdate = new JK.ClientUpdate()
|
||||
clientUpdate.initialize().check()
|
||||
|
||||
|
||||
|
||||
// Some things can't be initialized until we're connected. Put them here.
|
||||
function _initAfterConnect() {
|
||||
|
||||
|
|
@ -118,6 +122,7 @@
|
|||
|
||||
// This is a helper class with a singleton. No need to instantiate.
|
||||
JK.GenreSelectorHelper.initialize();
|
||||
JK.Banner.initialize();
|
||||
|
||||
var createSessionScreen = new JK.CreateSessionScreen(JK.app);
|
||||
createSessionScreen.initialize();
|
||||
|
|
@ -155,6 +160,8 @@
|
|||
JK.app = JK.JamKazam();
|
||||
JK.app.initialize();
|
||||
JK.JamServer.connect(); // singleton here defined in JamServer.js
|
||||
// this ensures that there is always a CurrentSessionModel, even if it's for a non-active session
|
||||
JK.CurrentSessionModel = new JK.SessionModel(JK.JamServer, window.jamClient);
|
||||
|
||||
// Run a check to see if we're logged in yet. Only after that should
|
||||
// we initialize the other screens.
|
||||
|
|
@ -173,4 +180,6 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<!-- version info: <%= version %> -->
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
<!-- footer links -->
|
||||
<div id="footer-links"><%= link_to "about", corp_about_path %> | <%= link_to "news", corp_news_path %> | <%= link_to "media", corp_media_center_path %> | <%= link_to "contact", corp_contact_path %> | <%= link_to "privacy", corp_privacy_path %> | <%= link_to "terms of service", corp_terms_path %> | <%= link_to "help", corp_help_path %></div>
|
||||
|
||||
<div><%= version %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -32,5 +32,7 @@
|
|||
<div id="footer-container">
|
||||
<%= render "clients/footer" %>
|
||||
</div>
|
||||
|
||||
<!-- version info: <%= version %> -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
7
build
7
build
|
|
@ -81,6 +81,13 @@ if [ -n "$PACKAGE" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
cat > lib/jam_web/version.rb << EOF
|
||||
module JamWeb
|
||||
VERSION = "0.1.$BUILD_NUMBER"
|
||||
end
|
||||
EOF
|
||||
|
||||
|
||||
type -P dpkg-architecture > /dev/null
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ if defined?(Bundler)
|
|||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
# config.autoload_paths += %W(#{config.root}/extras)
|
||||
config.autoload_paths += %W(#{config.root}/lib/managers)
|
||||
config.autoload_paths += %W(#{config.root}/lib)
|
||||
|
||||
# Only load the plugins named here, in the order given (default is alphabetical).
|
||||
# :all can be used as a placeholder for all plugins not explicitly named.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
module JamWeb
|
||||
VERSION = "0.0.1"
|
||||
end
|
||||
Loading…
Reference in New Issue