Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop
This commit is contained in:
commit
5370f8853b
|
|
@ -41,6 +41,7 @@ gem 'rails3-jquery-autocomplete'
|
|||
gem 'activeadmin'
|
||||
gem "meta_search", '>= 1.1.0.pre'
|
||||
gem 'fog', "~> 1.3.1"
|
||||
gem 'unf' #optional fog dependency
|
||||
gem 'country-select'
|
||||
gem 'aasm', '3.0.16'
|
||||
gem 'postgres-copy'
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"]');
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
you’re 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
|
||||
you’re 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>
|
||||
<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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue