Merge branch 'develop' into musicians_page

This commit is contained in:
Jonathan Kolyer 2013-11-03 23:43:21 -06:00
commit a8dbca3552
18 changed files with 692 additions and 100 deletions

View File

@ -33,21 +33,24 @@ group :assets do
end
gem 'will_paginate', '3.0.3'
gem 'bootstrap-will_paginate', '0.0.6'
gem 'carrierwave'
gem 'carrierwave', '0.9.0'
gem 'uuidtools', '2.1.2'
gem 'bcrypt-ruby', '3.0.1'
gem 'jquery-rails', '2.3.0' # pinned because jquery-ui-rails was split from jquery-rails, but activeadmin doesn't support this gem yet
gem 'rails3-jquery-autocomplete'
gem 'activeadmin'
gem "meta_search", '>= 1.1.0.pre'
gem 'fog', "~> 1.3.1"
gem 'activeadmin', '0.6.2'
gem 'mime-types', '1.25'
gem 'meta_search'
gem 'fog', "~> 1.18.0"
gem 'unf', '0.1.3' #optional fog dependency
gem 'country-select'
gem 'aasm', '3.0.16'
gem 'postgres-copy'
gem 'postgres-copy', '0.6.0'
gem 'aws-sdk'
gem 'bugsnag'
gem 'bugsnag'
gem 'eventmachine', '1.0.0'
gem 'eventmachine', '1.0.3'
gem 'amqp', '0.9.8'
gem 'logging-rails', :require => 'logging/rails'
@ -56,8 +59,8 @@ gem 'ruby-protocol-buffers', '1.2.2'
gem 'sendgrid', '1.1.0'
gem 'geokit-rails'
gem 'postgres_ext'
gem 'geokit-rails', '2.0.0'
gem 'postgres_ext', '1.0.0'
group :libv8 do
gem 'libv8', "~> 3.11.8"

View File

@ -47,6 +47,7 @@ gem 'aws-sdk', '1.8.0'
gem 'aasm', '3.0.16'
gem 'carrierwave'
gem 'fog'
gem 'unf' #optional fog dependency
gem 'devise', '>= 1.1.2'
#gem 'thin' # the presence of this gem on mac seems to prevent normal startup of rails.
gem 'postgres-copy'

View File

@ -245,7 +245,7 @@
$('#band-profile-biography').html(band.biography);
}
else {
logger.debug("No band found with bandId = " + bandId);
}
}
@ -266,7 +266,7 @@
function bindSocial() {
// FOLLOWERS
url = "/api/bands/" + bandId + "/followers";
var url = "/api/bands/" + bandId + "/followers";
$.ajax({
type: "GET",
dataType: "json",

View File

@ -178,6 +178,13 @@
function submitForm(evt) {
evt.preventDefault();
// If user hasn't completed FTUE - do so now.
if (!(context.jamClient.FTUEGetStatus())) {
app.afterFtue = function() { submitForm(evt); };
app.layout.showDialog('ftue');
return;
}
var isValid = validateForm();
if (!isValid) {
// app.notify({
@ -435,4 +442,4 @@
return this;
};
})(window,jQuery);
})(window,jQuery);

View File

@ -152,13 +152,15 @@
function containsInvitation(session) {
var i, invitation = null;
if ("invitations" in session) {
// user has invitations for this session
for (i=0; i < session.invitations.length; i++) {
invitation = session.invitations[i];
// session contains an invitation for this user
if (invitation.receiver_id == context.JK.currentUserId) {
return true;
if (session !== undefined) {
if ("invitations" in session) {
// user has invitations for this session
for (i=0; i < session.invitations.length; i++) {
invitation = session.invitations[i];
// session contains an invitation for this user
if (invitation.receiver_id == context.JK.currentUserId) {
return true;
}
}
}
}
@ -169,12 +171,14 @@
function containsFriend(session) {
var i, participant = null;
if ("participants" in session) {
for (i=0; i < session.participants.length; i++) {
participant = session.participants[i];
// this session participant is a friend
if (participant !== null && participant !== undefined && participant.user.is_friend) {
return true;
if (session !== undefined) {
if ("participants" in session) {
for (i=0; i < session.participants.length; i++) {
participant = session.participants[i];
// this session participant is a friend
if (participant !== null && participant !== undefined && participant.user.is_friend) {
return true;
}
}
}
}

View File

@ -25,6 +25,8 @@
};
var faderMap = {
'ftue-2-audio-input-fader': jamClient.FTUESetInputVolume,
'ftue-2-voice-input-fader': jamClient.FTUESetOutputVolume,
'ftue-audio-input-fader': jamClient.FTUESetInputVolume,
'ftue-voice-input-fader': jamClient.FTUESetChatInputVolume,
'ftue-audio-output-fader': jamClient.FTUESetOutputVolume
@ -44,6 +46,10 @@
function beforeShow(data) {
var vuMeters = [
'#ftue-2-audio-input-vu-left',
'#ftue-2-audio-input-vu-right',
'#ftue-2-voice-input-vu-left',
'#ftue-2-voice-input-vu-right',
'#ftue-audio-input-vu-left',
'#ftue-audio-input-vu-right',
'#ftue-voice-input-vu-left',
@ -80,6 +86,8 @@
// 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="0"] .settings-2-device select').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="0"] .settings-2-voice select').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .asio-settings .settings-driver select').val("");
}
@ -317,6 +325,15 @@
$('#asio-framesize').on('change', setAsioFrameSize);
$('#asio-input-latency').on('change', setAsioInputLatency);
$('#asio-output-latency').on('change', setAsioOutputLatency);
// New FTUE events
$('.ftue-new .settings-2-device select').on('change', newFtueAudioDeviceChanged);
$('.ftue-new .settings-2-voice select').on('change', newFtueAudioDeviceChanged);
$('#btn-ftue-2-asio-resync').on('click', newFtueAsioResync);
$('#btn-ftue-2-asio-control-panel').on('click', openASIOControlPanel);
$('#ftue-2-asio-framesize').on('change', newFtueSetAsioFrameSize);
$('#ftue-2-asio-input-latency').on('change', newFtueSetAsioInputLatency);
$('#ftue-2-asio-output-latency').on('change', newFtueSetAsioOutputLatency);
$('#btn-ftue-2-save').on('click', newFtueSaveSettingsHandler);
}
/**
@ -368,7 +385,6 @@
* Load available drivers and populate the driver select box.
*/
function loadAudioDrivers() {
var drivers = jamClient.FTUEGetDevices();
var driverOptionFunc = function(driverKey, index, list) {
@ -377,11 +393,249 @@
};
var optionsHtml = '<option selected="selected" value="">Choose...</option>';
var $select = $('[layout-wizard-step="2"] .settings-driver select');
$select.empty();
var selectors = [
'[layout-wizard-step="0"] .settings-2-device select',
'[layout-wizard-step="0"] .settings-2-voice select',
'[layout-wizard-step="2"] .settings-driver select'
];
var sortedDeviceKeys = context._.keys(drivers).sort();
context._.each(sortedDeviceKeys, driverOptionFunc);
$select.html(optionsHtml);
$.each(selectors, function(index, selector) {
var $select = $(selector);
$select.empty();
$select.html(optionsHtml);
});
}
/**
* Handler for the new FTUE save button.
*/
function newFtueSaveSettingsHandler(evt) {
evt.preventDefault();
var $saveButton = $('#btn-ftue-2-save');
if ($saveButton.hasClass('disabled')) {
return;
}
var selectedAudioDevice = $('.ftue-new .settings-2-device select').val();
if (!(selectedAudioDevice)) {
app.notify({
title: "Please select an audio device",
text: "Please choose a usable audio device, or select cancel."
});
return false;
}
jamClient.FTUESave(true);
jamClient.FTUESetStatus(true); // No FTUE wizard next time
rest.userCertifiedGear({success:true});
app.layout.closeDialog('ftue');
if (app.afterFtue) {
// If there's a function to invoke, invoke it.
app.afterFtue();
app.afterFtue = null;
}
return false;
}
// Handler for when the audio device is changed in the new FTUE screen
// This works differently from the old FTUE. There is no input/output selection,
// as soon as the user chooses a driver, we auto-assign inputs and outputs.
// We also call jamClient.FTUEGetExpectedLatency, which returns a structure like:
// { latency: 11.1875, latencyknown: true, latencyvar: 1}
function newFtueAudioDeviceChanged(evt) {
var $select = $(evt.currentTarget);
var $audioSelect = $('.ftue-new .settings-2-device select');
var $voiceSelect = $('.ftue-new .settings-2-voice select');
var audioDriverId = $audioSelect.val();
var voiceDriverId = $voiceSelect.val();
jamClient.FTUESetMusicDevice(audioDriverId);
jamClient.FTUESetChatInput(voiceDriverId);
if (voiceDriverId) { // Let the back end know whether a voice device is selected
jamClient.TrackSetChatEnable(true);
} else {
jamClient.TrackSetChatEnable(false);
}
if (!audioDriverId) {
// reset back to 'Choose...'
newFtueEnableControls(false);
return;
}
var musicInputs = jamClient.FTUEGetMusicInputs();
var musicOutputs = jamClient.FTUEGetMusicOutputs();
// set the music input to the first available input,
// and output to the first available output
var kin = null, kout = null, k = null;
// TODO FIXME - this jamClient call returns a dictionary.
// It's difficult to know what to auto-choose.
// For example, with my built-in audio, the keys I get back are
// digital in, line in, mic in and stereo mix. Which should we pick for them?
for (k in musicInputs) {
kin = k;
break;
}
for (k in musicOutputs) {
kout = k;
break;
}
var result;
if (kin && kout) {
jamClient.FTUESetMusicInput(kin);
jamClient.FTUESetMusicOutput(kout);
} else {
// TODO FIXME - how to handle a driver selection where we are unable to
// autoset both inputs and outputs? (I'd think this could happen if either
// the input or output side returned no values)
return;
}
newFtueEnableControls(true);
newFtueOsSpecificSettings();
setLevels(0);
newFtueUpdateLatencyView('loading');
jamClient.FTUESave(false);
setVuCallbacks();
var latency = jamClient.FTUEGetExpectedLatency();
newFtueUpdateLatencyView(latency);
}
function newFtueSave(persist) {
newFtueUpdateLatencyView('loading');
jamClient.FTUESave(persist);
var latency = jamClient.FTUEGetExpectedLatency();
newFtueUpdateLatencyView(latency);
}
function newFtueAsioResync(evt) {
// In theory, we should be calling the following, but it causes
// us to not have both inputs/outputs loaded, and simply calling
// FTUE Save appears to resync things.
//jamClient.FTUERefreshDevices();
newFtueSave(false);
}
function newFtueSetAsioFrameSize(evt) {
var val = parseFloat($(evt.currentTarget).val(),10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetFrameSize(" + val + ")");
jamClient.FTUESetFrameSize(val);
newFtueSave(false);
}
function newFtueSetAsioInputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(),10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetInputLatency(" + val + ")");
jamClient.FTUESetInputLatency(val);
newFtueSave(false);
}
function newFtueSetAsioOutputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(),10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
jamClient.FTUESetOutputLatency(val);
newFtueSave(false);
}
// Enable or Disable the frame/buffer controls in the new FTUE screen
function newFtueEnableControls(enable) {
var $frame = $('#ftue-2-asio-framesize');
var $bin = $('#ftue-2-asio-input-latency');
var $bout = $('#ftue-2-asio-output-latency');
if (enable) {
$frame.removeAttr("disabled");
$bin.removeAttr("disabled");
$bout.removeAttr("disabled");
} else {
$frame.attr("disabled", "disabled");
$bin.attr("disabled", "disabled");
$bout.attr("disabled", "disabled");
}
}
// Based on OS and Audio Hardware, set Frame/Buffer settings appropriately
// and show/hide the ASIO button.
function newFtueOsSpecificSettings() {
var $frame = $('#ftue-2-asio-framesize');
var $bin = $('#ftue-2-asio-input-latency');
var $bout = $('#ftue-2-asio-output-latency');
var $asioBtn = $('#btn-ftue-2-asio-control-panel');
if (jamClient.GetOSAsString() === "Win32") {
if (jamClient.FTUEHasControlPanel()) {
// Win32 + ControlPanel = ASIO
// frame=2.5, buffers=0
$asioBtn.show();
$frame.val(2.5);
$bin.val(0);
$bout.val(0);
} else {
// Win32, no ControlPanel = WDM/Kernel Streaming
// frame=10, buffers=0
$asioBtn.hide();
$frame.val(10);
// TODO FIXME - the old FTUE set the buffers to 1 for WDM/Kernel streaming
// The new FTUE spec says to use 0, as I've done here...
$bin.val(0);
$bout.val(0);
}
} else { // Assuming Mac. TODO: Linux check here
// frame=2.5, buffers=0
$asioBtn.hide();
$frame.val(2.5);
$bin.val(0);
$bout.val(0);
}
}
// Given a latency structure, update the view.
function newFtueUpdateLatencyView(latency) {
var $report = $('.ftue-new .latency .report');
var $instructions = $('.ftue-new .latency .instructions');
var latencyClass = "neutral";
var latencyValue = "N/A";
var $saveButton = $('#btn-ftue-2-save');
if (latency && latency.latencyknown) {
latencyValue = latency.latency;
// Round latency to two decimal places.
latencyValue = Math.round(latencyValue * 100) / 100;
if (latency.latency <= 10) {
latencyClass = "good";
$saveButton.removeClass('disabled');
} else if (latency.latency <= 20) {
latencyClass = "acceptable";
$saveButton.removeClass('disabled');
} else {
latencyClass = "bad";
$saveButton.addClass('disabled');
}
} else {
latencyClass = "unknown";
$saveButton.addClass('disabled');
}
$('.ms-label', $report).html(latencyValue);
$('p', $report).html('milliseconds');
$report.removeClass('good acceptable bad');
$report.addClass(latencyClass);
var instructionClasses = ['neutral', 'good', 'acceptable', 'bad', 'start', 'loading'];
$.each(instructionClasses, function(idx, val) {
$('p.' + val, $instructions).hide();
});
if (latency === 'loading') {
$('p.loading', $instructions).show();
} else {
$('p.' + latencyClass, $instructions).show();
}
}
function audioDriverChanged(evt) {
@ -459,6 +713,7 @@
var dialogBindings = { 'beforeShow': beforeShow,
'afterShow': afterShow, 'afterHide': afterHide };
app.bindDialog('ftue', dialogBindings);
app.registerWizardStepFunction("0", settingsInit);
app.registerWizardStepFunction("2", settingsInit);
app.registerWizardStepFunction("4", testLatency);
app.registerWizardStepFunction("6", testComplete);
@ -484,6 +739,8 @@
};
context.JK.ftueAudioInputVUCallback = function(dbValue) {
context.JK.ftueVUCallback(dbValue, '#ftue-2-audio-input-vu-left');
context.JK.ftueVUCallback(dbValue, '#ftue-2-audio-input-vu-right');
context.JK.ftueVUCallback(dbValue, '#ftue-audio-input-vu-left');
context.JK.ftueVUCallback(dbValue, '#ftue-audio-input-vu-right');
};
@ -492,6 +749,8 @@
context.JK.ftueVUCallback(dbValue, '#ftue-audio-output-vu-right');
};
context.JK.ftueChatInputVUCallback = function(dbValue) {
context.JK.ftueVUCallback(dbValue, '#ftue-2-voice-input-vu-left');
context.JK.ftueVUCallback(dbValue, '#ftue-2-voice-input-vu-right');
context.JK.ftueVUCallback(dbValue, '#ftue-voice-input-vu-left');
context.JK.ftueVUCallback(dbValue, '#ftue-voice-input-vu-right');
};

View File

@ -168,6 +168,14 @@
});
}
function getMusicianFollowers(userId) {
}
function getBandFollowers(bandId) {
}
function getClientDownloads(options) {
return $.ajax({

View File

@ -255,10 +255,6 @@
}
logger.debug("Changing screen to " + url);
context.location = url;
if (!(context.jamClient.FTUEGetStatus())) {
app.layout.showDialog('ftue');
}
}
this.unloadFunction = function() {
@ -294,6 +290,9 @@
}
};
// Holder for a function to invoke upon successfully completing the FTUE.
// See createSession.submitForm as an example.
this.afterFtue = null;
// enable temporary suspension of heartbeat for fine-grained control
this.heartbeatActive = true;

View File

@ -303,7 +303,9 @@
padding: '0px'
};
$('[layout]').css(layoutStyle);
$('[layout="notify"]').css({"z-index": "9", "padding": "20px"});
// JW: Setting z-index of notify to 1001, so it will appear above the dialog overlay.
// This allows dialogs to use the notification.
$('[layout="notify"]').css({"z-index": "1001", "padding": "20px"});
$('[layout="panel"]').css({position: 'relative'});
$('[layout-panel="expanded"] [layout-panel="header"]').css({
margin: "0px",
@ -381,12 +383,20 @@
function linkClicked(evt) {
evt.preventDefault();
var $currentTarget = $(evt.currentTarget);
// allow links to be disabled
if($(evt.currentTarget).hasClass("disabled") ) {
if($currentTarget.hasClass("disabled") ) {
return;
}
// If link requires FTUE, show that first.
if ($currentTarget.hasClass("requires-ftue")) {
if (!(context.jamClient.FTUEGetStatus())) {
app.layout.showDialog('ftue');
}
}
var destination = $(evt.currentTarget).attr('layout-link');
var destinationType = $('[layout-id="' + destination + '"]').attr("layout");
if (destinationType === "screen") {
@ -595,10 +605,11 @@
}
notifyQueue.push({message: message, descriptor: descriptor});
$notify.slideDown(2000)
.delay(2000)
// JW - speeding up the in/out parts of notify. Extending non-moving time.
$notify.slideDown(250)
.delay(4000)
.slideUp({
duration: 2000,
duration: 400,
queue: true,
complete: function() {
notifyDetails = notifyQueue.shift();
@ -614,7 +625,7 @@
}
}
});
}
};
function setNotificationInfo(message, descriptor) {
var $notify = $('[layout="notify"]');

View File

@ -307,22 +307,22 @@
$('#profile-location').html(user.location);
// stats
var text = user.friend_count > 1 || user.friend_count == 0 ? " Friends" : " Friend";
var text = user.friend_count > 1 || user.friend_count === 0 ? " Friends" : " Friend";
$('#profile-friend-stats').html(user.friend_count + text);
text = user.follower_count > 1 || user.follower_count == 0 ? " Followers" : " Follower";
text = user.follower_count > 1 || user.follower_count === 0 ? " Followers" : " Follower";
$('#profile-follower-stats').html(user.follower_count + text);
text = user.session_count > 1 || user.session_count == 0 ? " Sessions" : " Session";
text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
$('#profile-session-stats').html(user.session_count + text);
text = user.recording_count > 1 || user.recording_count == 0 ? " Recordings" : " Recording";
text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
$('#profile-recording-stats').html(user.recording_count + text);
$('#profile-biography').html(user.biography);
}
else {
logger.debug("No user found with userId = " + userId);
}
}

View File

@ -621,8 +621,6 @@
$connection.addClass(connectionClass);
} 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.
@ -632,7 +630,7 @@
} else {
// Examples of other events
// Add media file track: "add", "The_Abyss_4T", 0
logger.dbg('non-vu event: ' + eventName + ',' + mixerId + ',' + value);
logger.debug('non-vu event: ' + eventName + ',' + mixerId + ',' + value);
}
}
}

View File

@ -137,8 +137,16 @@
// wire up the Join Link to the T&Cs dialog
var $parentRow = $('tr[id=' + session.id + ']', tbGroup);
$('#join-link', $parentRow).click(function(evt) {
joinClick(session.id);
$('.join-link', $parentRow).click(function(evt) {
// If no FTUE, show that first.
if (!(context.jamClient.FTUEGetStatus())) {
app.afterFtue = function() { joinClick(session.id); };
app.layout.showDialog('ftue');
return;
} else {
joinClick(session.id);
}
});
}
}
@ -201,7 +209,7 @@
}
function openAlert(sessionId) {
var alertDialog = new context.JK.AlertDialog(app, "YES",
var alertDialog = new context.JK.AlertDialog(app, "YES",
"You must be approved to join this session. Would you like to send a request to join?",
sessionId, onCreateJoinRequest);
@ -210,7 +218,7 @@
}
function sessionNotJoinableAlert() {
var alertDialog = new context.JK.AlertDialog(app, "OK",
var alertDialog = new context.JK.AlertDialog(app, "OK",
"This session is over or is no longer public and cannot be joined. Please click Refresh to update the session list.",
null,
function(evt) {

View File

@ -110,6 +110,155 @@ div.dialog.ftue {
margin-top: 12px;
}
p.intro {
margin-top:0px;
}
.ftue-new {
clear:both;
position:relative;
width:100%;
height: 54px;
margin-top: 12px;
select {
font-size: 15px;
padding: 3px;
}
.latency {
position: absolute;
top: 120px;
font-size: 12px;
.report {
color:#fff;
position: absolute;
top: 20px;
left: 0px;
width: 105px;
height: 50px;
background-color: #72a43b;
padding: 10px;
text-align: center;
.ms-label {
padding-top: 10px;
font-size: 34px;
font-family: Arial, sans-serif;
}
p {
margin-top: 4px;
}
}
.report.neutral, .report.start, .report.unknown {
background-color: #666;
}
.report.good {
background-color: #72a43b;
}
.report.acceptable {
background-color: #D6A800;
}
.report.bad {
background-color: #7B0C00;
}
.instructions {
color:#fff;
position: absolute;
top: 20px;
left: 125px;
width: 595px;
height: 50px;
padding: 10px;
background-color: #666;
}
.instructions p.start, .instructions p.neutral {
padding-top: 4px;
}
.instructions p.unknown {
margin-top:0px;
padding-top: 4px;
}
.instructions p.good {
padding-top: 4px;
}
.instructions p.acceptable {
margin-top: -6px;
}
.instructions p.bad {
margin-top: -6px;
}
.instructions p a {
font-weight: bold;
}
}
.column {
position:absolute;
width: 220px;
height: 50px;
margin-right:8px;
}
.settings-2-device {
left:0px;
}
.settings-2-center {
left:50%;
margin-left: -110px;
.buttons {
margin-top: 14px;
a {
margin-right: 0px;
}
}
}
.settings-2-voice {
top: 0px;
right:0px;
}
.controls {
margin-top: 16px;
background-color: #222;
height: 48px;
width: 220px;
}
.ftue-vu-left {
position:relative;
top: 0px;
}
.ftue-vu-right {
position:relative;
top: 22px;
}
.ftue-fader {
position:relative;
top: 14px;
left: 8px;
}
.gain-label {
color: $ColorScreenPrimary;
position:absolute;
top: 76px;
right: 6px;
}
.subcolumn {
position:absolute;
top: 60px;
font-size: 12px !important;
width: 68px;
height: 48px;
}
.subcolumn select {
width: 68px;
}
.subcolumn.first {
left:0px;
}
.subcolumn.second {
left:50%;
margin-left:-34px;
}
.subcolumn.third {
right:0px;
}
}
.asio-settings {
clear:both;
position:relative;

View File

@ -72,7 +72,7 @@
</a>
</td>
<td class="noborder" style="text-align:center; vertical-align:middle;">
<a id="join-link" style="display:{join_link_display_style};">
<a class="join-link" style="display:{join_link_display_style};">
<%= image_tag "content/icon_join.png", :size => "19x22" %>
</a>
</td>

View File

@ -7,8 +7,128 @@
<!-- inner wrapper -->
<div class="ftue-inner" layout-wizard="ftue">
<!-- NEW FTUE first screen, which has latency approximation -->
<!-- Audio device selection and level-setting -->
<div layout-wizard-step="0" dialog-title="audio gear settings" dialog-purpose="GearSettings" style="display:block;">
<p os="win32" class="intro">
Choose a device to capture and play your session audio. If
youre not using a mic with this device, then also choose a
voice chat input to talk with others during sessions. Then play
and speak, and adjust the gain faders so that you hear both your
instrument and voice in your headphones at comfortable volumes.
</p>
<p os="mac" class="intro" style="display:none;">
Choose a device to capture and play your session audio. If
youre not using a mic with this device, then also choose a
voice chat input to talk with others during sessions. Then play
and speak, and adjust the gain faders so that you hear both your
instrument and voice in your headphones at comfortable volumes.
</p>
<div class="ftue-new">
<div class="column settings-2-device">
Session Audio Device:<br />
<select></select>
<!-- VU/Fader for audio device -->
<div class="controls">
<div id="ftue-2-audio-input-vu-left" class="ftue-vu-left"></div>
<div id="ftue-2-audio-input-fader" class="ftue-fader"></div>
<div class="gain-label">GAIN</div>
<div id="ftue-2-audio-input-vu-right" class="ftue-vu-right"></div>
</div>
</div>
<div class="column settings-2-center">
<div class="buttons">
<a class="button-grey" id="btn-ftue-2-asio-resync">
<%= image_tag "content/icon_resync.png", {:width => 12, :height => 14} %>
RESYNC
</a>
<a class="button-grey" id="btn-ftue-2-asio-control-panel">ASIO SETTINGS</a>
</div>
<div class="subcolumn first">
Frame<br />
<select disabled="disabled" id="ftue-2-asio-framesize">
<option value=""></option>
<option value="2.5">2.5</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
</div>
<div class="subcolumn second">
Buffer/In<br />
<select disabled="disabled" id="ftue-2-asio-input-latency">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
</div>
<div class="subcolumn third">
Buffer/Out<br />
<select disabled="disabled" id="ftue-2-asio-output-latency">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
</div>
</div>
<!-- Colum 3: Voice -->
<div class="column settings-2-voice">
Voice Chat Input:<br />
<select></select>
<div class="controls">
<div id="ftue-2-voice-input-vu-left" class="ftue-vu-left"></div>
<div id="ftue-2-voice-input-fader" class="ftue-fader"></div>
<div class="gain-label">GAIN</div>
<div id="ftue-2-voice-input-vu-right" class="ftue-vu-right"></div>
</div>
</div>
<!-- Latency -->
<div class="latency">
Latency:<br />
<div class="report neutral">
<div class="ms-label"></div>
<p></p>
</div>
<div class="instructions">
<p class="start" style="display:block;">Choose an audio device to continue...</p>
<p class="unknown" style="display:none;">Unable to determine latency. Please click <a href="#" layout-wizard-link="2">here</a> to try another test which may be able to determine your audio performance.</p>
<p class="neutral loading" style="display:none;">Estimating latency...</p>
<p class="good" style="display:none;">Your audio speed is good. When done with settings, click Save Settings to continue.</p>
<p class="acceptable" style="display:none;">Your audio speed is acceptable, but borderline. Try setting Frame to 2.5 and Buffers to 0 and see if your audio quality is still OK. When done with settings, click Save Settings to continue. You can also view the <a href="#">Choosing an Audio Device</a> article for information on faster audio devices.</p>
<p class="bad" style="display:none;">We're sorry, but your audio speed is too slow to use JamKazam. Try setting Frame to 2.5 and Buffers to 0 and see if your audio quality is still OK. You can also view the <a href="#">Choosing an Audio Device</a> article for information on faster audio devices.</p>
</div>
</div>
</div>
<div class="right mr30 buttonbar">
<a class="button-grey" layout-action="close">CANCEL</a>
<a class="button-grey">HELP</a>&nbsp;
<a class="button-orange" id="btn-ftue-2-save">SAVE SETTINGS</a>
</div>
</div>
<!-- First screen of the FTUE wizard -->
<div layout-wizard-step="1" dialog-title="welcome!" dialog-purpose="Intro" style="display:block;">
<div layout-wizard-step="1" dialog-title="welcome!" dialog-purpose="Intro" style="display:none;">
<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 one to

View File

@ -31,33 +31,6 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
it "finds another public session", :slow => true do
@unique_session_desc = 'Description found easily'
# create session in one client
in_client(:one) do
page.driver.resize(1500, 600) # crude hack
sign_in_poltergeist user
visit "/client#/createSession"
within('#create-session-form') do
fill_in('description', :with => @unique_session_desc)
select('Rock', :from => 'genres')
find('div.intellectual-property ins').trigger(:click)
click_link('btn-create-session') # fails if page width is low
end
# verify that the in-session page is showing
expect(page).to have_selector('h2', text: 'my tracks')
end
# find session in second client
in_client(:two) do
sign_in_poltergeist finder
visit "/client#/findSession"
# verify the session description is seen by second client
expect(page).to have_text(@unique_session_desc)
end
create_join_session(user, [finder])
end
end

View File

@ -2,20 +2,6 @@ require 'spec_helper'
describe "Music Session", :js => true, :type => :feature, :capybara_feature => true, :slow => true do
def create_music_session
uu = FactoryGirl.create(:user)
sign_in_poltergeist uu
visit "/client#/createSession"
sleep 3
within('#create-session-form') do
fill_in('description', :with => 'foobar')
select('Ambient', :from => 'genres')
find('div.intellectual-property ins').trigger(:click)
click_link('btn-create-session')
end
uu
end
def leave_music_session_sleep_delay
# add a buffer to ensure WSG has enough time to expire
sleep_dur = (Rails.application.config.websocket_gateway_connect_time_stale +
@ -42,7 +28,7 @@ describe "Music Session", :js => true, :type => :feature, :capybara_feature => t
before(:each) do
UserMailer.deliveries.clear
pending
@user1 = create_music_session
@user1, session_description = create_session
end
describe "cleanly leaves music session" do
@ -77,14 +63,14 @@ describe "Music Session", :js => true, :type => :feature, :capybara_feature => t
before(:each) do
UserMailer.deliveries.clear
in_client(:user1_music_session) do
@user1 = create_music_session
@user1, session_description = create_session
end
end
describe "cleanly leaves" do
it "should update music session and user session history" do
in_client(:user2_music_session) do
@user2 = create_music_session
@user2, session_description = create_session
sleep 5
should have_link('session-leave')
click_link('session-leave')
@ -100,7 +86,7 @@ describe "Music Session", :js => true, :type => :feature, :capybara_feature => t
describe "abruptly leaves" do
it "should update music session and user session history" do
in_client(:user2_music_session) do
@user2 = create_music_session
@user2, session_description = create_session
sleep 5
should have_link('session-leave')
page.evaluate_script("JK.JamServer.close(true)")

View File

@ -6,7 +6,7 @@ end
def in_client(name) # to assist multiple-client RSpec/Capybara testing
Capybara.session_name = name
Capybara.session_name = name.class == JamRuby::User ? name.id : name
yield
end
@ -70,4 +70,70 @@ end
def wait_until_curtain_gone
should have_no_selector('.curtain')
end
def determine_test_name(metadata, test_name_buffer = '')
description = metadata[:description_args]
if description.kind_of?(Array)
description = description[0]
end
if metadata.has_key? :example_group
return determine_test_name(metadata[:example_group], "#{description} #{test_name_buffer}")
else
return "#{description} #{test_name_buffer}"
end
end
# takes, or creates, a unique session description which is returned for subsequent calls to join_session to use
# in finding this session)
def create_session(creator = FactoryGirl.create(:user), unique_session_desc = "create_join_session #{SecureRandom.urlsafe_base64}")
# create session in one client
in_client(creator) do
page.driver.resize(1500, 600) # makes sure all the elements are visible
sign_in_poltergeist creator
wait_until_curtain_gone
visit "/client#/createSession"
expect(page).to have_selector('h2', text: 'session info')
within('#create-session-form') do
fill_in('description', :with => unique_session_desc)
select('Rock', :from => 'genres')
find('div.intellectual-property ins').trigger(:click)
find('#btn-create-session').trigger(:click) # fails if page width is low
end
# verify that the in-session page is showing
expect(page).to have_selector('h2', text: 'my tracks')
end
return creator, unique_session_desc
end
# this code assumes that there are no music sessions in the database. it should fail on the
# find('.join-link') call if > 1 session exists because capybara will complain of multile matches
def join_session(joiner, unique_session_desc)
in_client(joiner) do
sign_in_poltergeist joiner
wait_until_curtain_gone
visit "/client#/findSession"
# verify the session description is seen by second client
expect(page).to have_text(unique_session_desc)
find('.join-link').trigger(:click)
find('#btn-accept-terms').trigger(:click)
expect(page).to have_selector('h2', text: 'my tracks')
end
end
def create_join_session(creator, joiners=[])
creator, unique_session_desc = create_session(creator)
# find session in second client
joiners.each do |joiner|
join_session(joiner, unique_session_desc)
end
end