913 lines
27 KiB
JavaScript
913 lines
27 KiB
JavaScript
/**
|
|
* Common utility functions.
|
|
*/
|
|
(function (context, $) {
|
|
|
|
"use strict";
|
|
|
|
context.JK = context.JK || {};
|
|
var logger = context.JK.logger;
|
|
|
|
var days = new Array("Sun", "Mon", "Tue",
|
|
"Wed", "Thu", "Fri", "Sat");
|
|
|
|
var months = new Array("January", "February", "March",
|
|
"April", "May", "June", "July", "August", "September",
|
|
"October", "November", "December");
|
|
|
|
|
|
context.JK.stringToBool = function (s) {
|
|
switch (s.toLowerCase()) {
|
|
case "true":
|
|
case "yes":
|
|
case "1":
|
|
return true;
|
|
case "false":
|
|
case "no":
|
|
case "0":
|
|
case null:
|
|
return false;
|
|
default:
|
|
return Boolean(s);
|
|
}
|
|
};
|
|
|
|
// http://stackoverflow.com/a/8809472/834644
|
|
context.JK.generateUUID = function () {
|
|
var d = new Date().getTime();
|
|
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
var r = (d + Math.random() * 16) % 16 | 0;
|
|
d = Math.floor(d / 16);
|
|
return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
|
|
});
|
|
return uuid;
|
|
};
|
|
|
|
// Build up two maps of images, for each instrument id.
|
|
// This map is a simple base map of instrument id to the basic image name.
|
|
// Below, a loop goes through this and builds two size-specific maps.
|
|
// In the future, we should test Whether having a single larger image
|
|
// available, and allowing the browser to resize offers better quality.
|
|
var icon_map_base = {
|
|
"accordion": "accordion",
|
|
"acoustic guitar": "acoustic_guitar",
|
|
"banjo": "banjo",
|
|
"bass guitar": "bass_guitar",
|
|
"cello": "cello",
|
|
"clarinet": "clarinet",
|
|
"computer": "computer",
|
|
"default": "default",
|
|
"drums": "drums",
|
|
"electric guitar": "electric_guitar",
|
|
"euphonium": "euphonium",
|
|
"flute": "flute",
|
|
"french horn": "french_horn",
|
|
"harmonica": "harmonica",
|
|
"keyboard": "keyboard",
|
|
"mandolin": "mandolin",
|
|
"oboe": "oboe",
|
|
"other": "other",
|
|
"piano": "piano",
|
|
"saxophone": "saxophone",
|
|
"trombone": "trombone",
|
|
"trumpet": "trumpet",
|
|
"tuba": "tuba",
|
|
"ukulele": "ukelele",
|
|
"upright bass": "upright_bass",
|
|
"viola": "viola",
|
|
"violin": "violin",
|
|
"voice": "voice"
|
|
};
|
|
|
|
var instrumentIconMap24 = {};
|
|
var instrumentIconMap45 = {};
|
|
|
|
$.each(context._.keys(icon_map_base), function (index, instrumentId) {
|
|
var icon = icon_map_base[instrumentId];
|
|
instrumentIconMap24[instrumentId] = "/assets/content/icon_instrument_" + icon + "24.png";
|
|
instrumentIconMap45[instrumentId] = "/assets/content/icon_instrument_" + icon + "45.png";
|
|
});
|
|
|
|
/**
|
|
* Associates a help bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
|
* @param $element The element that should show the help when hovered
|
|
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.erb
|
|
* @param data (optional) data for your template, if applicable
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*
|
|
*/
|
|
context.JK.helpBubble = function ($element, templateName, data, options) {
|
|
if (!data) {
|
|
data = {}
|
|
}
|
|
var helpText = context._.template($('#template-help-' + templateName).html(), data, { variable: 'data' });
|
|
|
|
var holder = $('<div class="hover-bubble help-bubble"></div>');
|
|
holder.append(helpText);
|
|
|
|
context.JK.hoverBubble($element, helpText, options);
|
|
}
|
|
|
|
/**
|
|
* Associates a bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
|
* @param $element The element that should show the bubble when hovered
|
|
* @param text the text or jquery element that should be shown as contents of the bubble
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*/
|
|
context.JK.hoverBubble = function ($element, text, options) {
|
|
if (!text) {
|
|
logger.error("hoverBubble: no text to attach to $element %o", $element);
|
|
return;
|
|
}
|
|
|
|
if ($element instanceof jQuery) {
|
|
if ($element.length == 0) {
|
|
logger.error("hoverBubble: no element specified with text %o", text);
|
|
return;
|
|
}
|
|
}
|
|
|
|
var defaultOpts = {
|
|
fill: '#333',
|
|
strokeStyle: '#ED3618',
|
|
spikeLength: 10,
|
|
spikeGirth: 10,
|
|
padding: 8,
|
|
cornerRadius: 0,
|
|
cssStyles: {
|
|
fontSize: '11px',
|
|
color: 'white',
|
|
whiteSpace: 'normal'
|
|
}
|
|
};
|
|
|
|
if (options) {
|
|
options = $.extend(false, defaultOpts, options);
|
|
}
|
|
else {
|
|
options = defaultOpts;
|
|
}
|
|
|
|
$element.bt(text, options);
|
|
}
|
|
|
|
context.JK.bindHoverEvents = function ($parent) {
|
|
|
|
if(!$parent) {
|
|
$parent = $('body');
|
|
}
|
|
|
|
function showBubble(bubble, $hoverElement) {
|
|
$hoverElement.attr("bubble-id", bubble.id);
|
|
bubble.showBubble();
|
|
}
|
|
|
|
function hideBubble($hoverElement) {
|
|
var bubbleSelector = $hoverElement.attr("bubble-id");
|
|
$(bubbleSelector).hover(
|
|
function () {
|
|
// do nothing when entering the bubble (this should never happen)
|
|
},
|
|
function () {
|
|
$(this).fadeOut(500);
|
|
}
|
|
);
|
|
}
|
|
|
|
// MUSICIAN
|
|
$("[hoveraction='musician']", $parent).hoverIntent({
|
|
over: function () {
|
|
var bubble = new JK.MusicianHoverBubble($(this).attr('user-id'), $(this).offset());
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: 1
|
|
});
|
|
|
|
// FAN
|
|
$("[hoveraction='fan']", $parent).hoverIntent({
|
|
over: function () {
|
|
var bubble = new JK.FanHoverBubble($(this).attr('user-id'), $(this).offset());
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: 1
|
|
});
|
|
|
|
// BAND
|
|
$("[hoveraction='band']", $parent).hoverIntent({
|
|
over: function () {
|
|
var bubble = new JK.BandHoverBubble($(this).attr('band-id'), $(this).offset());
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: 1
|
|
});
|
|
|
|
// SESSION
|
|
$("[hoveraction='session']", $parent).hoverIntent({
|
|
over: function () {
|
|
var bubble = new JK.SessionHoverBubble($(this).attr('session-id'), $(this).offset());
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: 1
|
|
});
|
|
|
|
// RECORDING
|
|
$("[hoveraction='recording']", $parent).hoverIntent({
|
|
over: function () {
|
|
var bubble = new JK.RecordingHoverBubble($(this).attr('recording-id'), $(this).offset());
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: 1
|
|
});
|
|
}
|
|
|
|
context.JK.fetchUserNetworkOrServerFailure = function () {
|
|
JK.app.notify({
|
|
title: "Unable to communicate with server",
|
|
text: "Please try again later",
|
|
icon_url: "/assets/content/icon_alert_big.png"
|
|
});
|
|
}
|
|
|
|
context.JK.entityNotFound = function (type) {
|
|
JK.app.notify({
|
|
title: type + " Deleted",
|
|
text: "The " + type + " no longer exists.",
|
|
icon_url: "/assets/content/icon_alert_big.png"
|
|
});
|
|
}
|
|
|
|
|
|
// Uber-simple templating
|
|
// var template = "Hey {name}";
|
|
// var vals = { name: "Jon" };
|
|
// _fillTemplate(template, vals);
|
|
// --> "Hey Jon"
|
|
//
|
|
// use context._.template for something more powerful
|
|
context.JK.fillTemplate = function (template, vals) {
|
|
if (template == null) throw 'null template in fillTemplate'
|
|
for (var val in vals)
|
|
template = template.replace(new RegExp('{' + val + '}', 'g'), vals[val]);
|
|
return template;
|
|
};
|
|
|
|
context.JK.resolveAvatarUrl = function (photo_url) {
|
|
return photo_url ? photo_url : "/assets/shared/avatar_generic.png";
|
|
};
|
|
|
|
context.JK.resolveBandAvatarUrl = function (photo_url) {
|
|
return photo_url ? photo_url : "/assets/shared/avatar_generic_band.png";
|
|
};
|
|
|
|
context.JK.getInstrumentIconMap24 = function () {
|
|
return instrumentIconMap24;
|
|
};
|
|
|
|
context.JK.getInstrumentIconMap45 = function () {
|
|
return instrumentIconMap45;
|
|
};
|
|
|
|
context.JK.getInstrumentIcon24 = function (instrument) {
|
|
if (instrument in instrumentIconMap24) {
|
|
return instrumentIconMap24[instrument];
|
|
}
|
|
|
|
return instrumentIconMap24["default"];
|
|
};
|
|
|
|
context.JK.getInstrumentIcon45 = function (instrument) {
|
|
if (instrument in instrumentIconMap45) {
|
|
return instrumentIconMap45[instrument];
|
|
}
|
|
|
|
return instrumentIconMap45["default"];
|
|
};
|
|
|
|
// meant to pass in a bunch of images with an instrument-id attribute on them.
|
|
|
|
context.JK.setInstrumentAssetPath = function ($elements) {
|
|
$.each($elements, function (index, item) {
|
|
var $element = $(this);
|
|
if (!$element.is('img')) {
|
|
throw "expected to receive an <img> in setInstrumentAssetPath"
|
|
}
|
|
|
|
var instrument = $element.attr('instrument-id');
|
|
|
|
$element.attr('src', context.JK.getInstrumentIcon24(instrument))
|
|
})
|
|
}
|
|
|
|
// creates an array with entries like [{ id: "drums", description: "Drums"}, ]
|
|
context.JK.listInstruments = function() {
|
|
var instrumentArray = [];
|
|
$.each(context.JK.server_to_client_instrument_map, function(key, val) {
|
|
instrumentArray.push({"id": context.JK.server_to_client_instrument_map[key].client_id, "description": key});
|
|
});
|
|
return instrumentArray;
|
|
}
|
|
|
|
context.JK.showErrorDialog = function (app, msg, title) {
|
|
app.layout.showDialog('error-dialog');
|
|
$('#error-msg', 'div[layout-id="error-dialog"]').html(msg);
|
|
$('#error-summary', 'div[layout-id="error-dialog"]').html(title);
|
|
}
|
|
|
|
// TODO: figure out how to handle this in layout.js for layered popups
|
|
context.JK.showOverlay = function () {
|
|
$('.dialog-overlay').show();
|
|
}
|
|
|
|
context.JK.hideOverlay = function () {
|
|
$('.dialog-overlay').hide();
|
|
}
|
|
|
|
/*
|
|
* Loads a listbox or dropdown with the values in input_array, setting the option value
|
|
* to the id_field and the option text to text_field. It will preselect the option with
|
|
* value equal to selected_id.
|
|
*/
|
|
context.JK.loadOptions = function (templateHtml, listbox_id, input_array, id_field, text_field, selected_id) {
|
|
$.each(input_array, function (index, val) {
|
|
var isSelected = "";
|
|
if (val[id_field] === selected_id) {
|
|
isSelected = "selected";
|
|
}
|
|
var html = context.JK.fillTemplate(templateHtml, {
|
|
value: val[id_field],
|
|
label: val[text_field],
|
|
selected: isSelected
|
|
});
|
|
|
|
listbox_id.append(html);
|
|
});
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
context.JK.formatDateTime = function (dateString) {
|
|
var date = new Date(dateString);
|
|
return context.JK.padString(date.getMonth() + 1, 2) + "/" + context.JK.padString(date.getDate(), 2) + "/" + date.getFullYear() + " - " + date.toLocaleTimeString();
|
|
}
|
|
|
|
// returns Fri May 20, 2013
|
|
context.JK.formatDate = function (dateString) {
|
|
var date = new Date(dateString);
|
|
|
|
return days[date.getDay()] + ' ' + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear();
|
|
}
|
|
|
|
context.JK.formatTime = function (dateString) {
|
|
var date = new Date(dateString);
|
|
return date.toLocaleTimeString();
|
|
}
|
|
|
|
context.JK.prettyPrintElements = function ($elements) {
|
|
$.each($elements, function (index, item) {
|
|
var $item = $(item);
|
|
$item.text(context.JK.prettyPrintSeconds(parseInt($item.attr('duration'))))
|
|
});
|
|
}
|
|
|
|
context.JK.prettyPrintSeconds = function (seconds) {
|
|
// from: http://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
|
|
// Minutes and seconds
|
|
var mins = ~~(seconds / 60);
|
|
var secs = seconds % 60;
|
|
|
|
// Hours, minutes and seconds
|
|
var hrs = ~~(seconds / 3600);
|
|
var mins = ~~((seconds % 3600) / 60);
|
|
var secs = seconds % 60;
|
|
|
|
// Output like "1:01" or "4:03:59" or "123:03:59"
|
|
var ret = "";
|
|
|
|
if (hrs > 0)
|
|
ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
|
|
|
|
ret += "" + mins + ":" + (secs < 10 ? "0" : "");
|
|
ret += "" + secs;
|
|
return ret;
|
|
}
|
|
|
|
context.JK.search = function (query, app, callback) {
|
|
//logger.debug("search: "+ query)
|
|
$.ajax({
|
|
type: "GET",
|
|
dataType: "json",
|
|
contentType: 'application/json',
|
|
url: "/api/search?query=" + query,
|
|
processData: false,
|
|
success: function (response) {
|
|
callback(response);
|
|
},
|
|
error: app.ajaxError
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Get the length of a dictionary
|
|
*/
|
|
context.JK.dlen = function (d) {
|
|
var count = 0;
|
|
for (var i in d) {
|
|
if (d.hasOwnProperty(i)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
};
|
|
|
|
/*
|
|
* Get the keys of a dictionary as an array (same as Object.keys, but works in all browsers)
|
|
*/
|
|
context.JK.dkeys = function (d) {
|
|
var keys = []
|
|
for (var i in d) {
|
|
if (d.hasOwnProperty(i)) {
|
|
keys.push(i);
|
|
}
|
|
}
|
|
return keys;
|
|
};
|
|
|
|
/**
|
|
* Finds the first error associated with the field.
|
|
* @param fieldName the name of the field
|
|
* @param errors_data response from a 422 response in ajax
|
|
* @returns null if no error for the field name, or the 1st error associated with that field
|
|
*/
|
|
context.JK.get_first_error = function (fieldName, errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return null;
|
|
|
|
if (errors[fieldName] && errors[fieldName].length > 0) {
|
|
return errors[fieldName][0]
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a ul with an li per field name.
|
|
* @param fieldName the name of the field
|
|
* @param errors_data error data return by a 422 ajax response
|
|
* @returns null if no error for the field name; otherwise a ul/li
|
|
*/
|
|
context.JK.format_errors = function (fieldName, errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return null;
|
|
|
|
var field_errors = errors[fieldName];
|
|
if (field_errors == null) {
|
|
return null;
|
|
}
|
|
|
|
var ul = $('<ul class="error-text"></ul>');
|
|
|
|
$.each(field_errors, function (index, item) {
|
|
ul.append(context.JK.fillTemplate("<li>{message}</li>", {message: item}))
|
|
})
|
|
|
|
return ul;
|
|
}
|
|
|
|
context.JK.format_all_errors = function (errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return $('<ul class="error-text"><li>unknown error</li></ul>');
|
|
|
|
var ul = $('<ul class="error-text"></ul>');
|
|
|
|
$.each(errors, function (fieldName, field_errors) {
|
|
|
|
$.each(field_errors, function (index, item) {
|
|
ul.append(context.JK.fillTemplate("<li>{field} {message}</li>", {field: fieldName, message: item}))
|
|
});
|
|
});
|
|
|
|
return ul;
|
|
}
|
|
|
|
|
|
/**
|
|
* Way to verify that a number of parallel tasks have all completed.
|
|
* Provide a function to evaluate completion, and a callback to
|
|
* invoke when that function evaluates to true.
|
|
* NOTE: this does not pause execution, it simply ensures that
|
|
* when the test function evaluates to true, the callback will
|
|
* be invoked.
|
|
*/
|
|
context.JK.joinCalls = function (completionTestFunction, callback, interval) {
|
|
function doneYet() {
|
|
if (completionTestFunction()) {
|
|
callback();
|
|
} else {
|
|
context.setTimeout(doneYet, interval);
|
|
}
|
|
}
|
|
|
|
doneYet();
|
|
};
|
|
|
|
/**
|
|
* Returns 'MacOSX' if the os appears to be macintosh,
|
|
* 'Win32' if the os appears to be windows,
|
|
* 'Unix' if the OS appears to be linux,
|
|
* and null if unknown
|
|
* @returns {*}
|
|
*/
|
|
context.JK.detectOS = function () {
|
|
if (!navigator.platform) {
|
|
return null;
|
|
}
|
|
|
|
if (navigator.platform.toLowerCase().indexOf('mac') !== -1) {
|
|
return "MacOSX";
|
|
}
|
|
if (navigator.platform.toLowerCase().indexOf('win') !== -1) {
|
|
return "Win32"
|
|
}
|
|
if (navigator.platform.toLowerCase().indexOf('linux') !== -1) {
|
|
return "Unix"
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
context.JK.popExternalLinks = function () {
|
|
// Allow any a link with a rel="external" attribute to launch
|
|
// the link in the default browser, using jamClient:
|
|
$('body').on('click', 'a[rel="external"]', function (evt) {
|
|
|
|
if (!context.jamClient) {
|
|
return;
|
|
}
|
|
|
|
evt.preventDefault();
|
|
var href = $(this).attr("href");
|
|
if (href) {
|
|
// make absolute if not already
|
|
if (href.indexOf('http') != 0 && href.indexOf('mailto') != 0) {
|
|
href = window.location.protocol + '//' + window.location.host + href;
|
|
}
|
|
|
|
context.jamClient.OpenSystemBrowser(href);
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
context.JK.popExternalLink = function (href) {
|
|
if (!context.jamClient) {
|
|
return;
|
|
}
|
|
|
|
if (href) {
|
|
// make absolute if not already
|
|
if (href.indexOf('http') != 0 && href.indexOf('mailto') != 0) {
|
|
href = window.location.protocol + '//' + window.location.host + href;
|
|
}
|
|
|
|
context.jamClient.OpenSystemBrowser(href);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
context.JK.checkbox = function ($checkbox) {
|
|
$checkbox.iCheck({
|
|
checkboxClass: 'icheckbox_minimal',
|
|
radioClass: 'iradio_minimal',
|
|
inheritClass: true
|
|
});
|
|
}
|
|
|
|
context.JK.dropdown = function ($select) {
|
|
|
|
$select.each(function (index) {
|
|
var $item = $(this);
|
|
|
|
if ($item.data('easydropdown-select')) {
|
|
// if this has already been initialized, re-init it so it picks up any new <options>
|
|
$item.easyDropDown('destroy')
|
|
}
|
|
$item.easyDropDown({nativeTouch: !(context.jamClient && context.jamClient.IsNativeClient()) && gon.global.env != "test", cutOff: 7});
|
|
})
|
|
}
|
|
|
|
context.JK.hasFlash = function () {
|
|
var hasFlash = false;
|
|
|
|
if (!context.jamClient || !context.jamClient.IsNativeClient()) {
|
|
try {
|
|
var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
|
|
if (fo) hasFlash = true;
|
|
} catch (e) {
|
|
if (navigator.mimeTypes ["application/x-shockwave-flash"] != undefined) hasFlash = true;
|
|
}
|
|
}
|
|
|
|
return hasFlash;
|
|
}
|
|
|
|
context.JK.hasOneConfiguredDevice = function() {
|
|
var result = context.jamClient.FTUEGetGoodConfigurationList();
|
|
console.log("hasOneConfiguredDevice: ", result);
|
|
return result.length > 0;
|
|
};
|
|
|
|
context.JK.getGoodAudioConfigs = function() {
|
|
var result = context.jamClient.FTUEGetGoodAudioConfigurations();
|
|
console.log("goodAudioConfigs=%o", result);
|
|
return result;
|
|
};
|
|
|
|
context.JK.getGoodConfigMap = function() {
|
|
var goodConfigMap = [];
|
|
var goodConfigs = context.JK.getGoodAudioConfigs();
|
|
$.each(goodConfigs, function(index, profileKey) {
|
|
var friendlyName = context.jamClient.FTUEGetConfigurationDevice(profileKey);
|
|
goodConfigMap.push({key: profileKey, name: friendlyName});
|
|
});
|
|
|
|
return goodConfigMap;
|
|
}
|
|
|
|
context.JK.getBadAudioConfigs = function() {
|
|
var badAudioConfigs = [];
|
|
var allAudioConfigs = context.jamClient.FTUEGetAllAudioConfigurations();
|
|
var goodAudioConfigs = context.JK.getGoodAudioConfigs();
|
|
|
|
for (var i=0; i < allAudioConfigs.length; i++) {
|
|
if ($.inArray(allAudioConfigs[i], goodAudioConfigs) === -1) {
|
|
badAudioConfigs.push(allAudioConfigs[i]);
|
|
}
|
|
}
|
|
console.log("badAudioConfigs=%o", badAudioConfigs);
|
|
return badAudioConfigs;
|
|
};
|
|
|
|
context.JK.getBadConfigMap = function() {
|
|
var badConfigMap = [];
|
|
var badConfigs = context.JK.getBadAudioConfigs();
|
|
$.each(badConfigs, function(index, profileKey) {
|
|
var friendlyName = context.jamClient.FTUEGetConfigurationDevice(profileKey);
|
|
badConfigMap.push({key: profileKey, name: friendlyName});
|
|
});
|
|
|
|
return badConfigMap;
|
|
}
|
|
|
|
context.JK.getFirstGoodDevice = function(preferredDeviceId) {
|
|
var badConfigs = context.JK.getBadAudioConfigs();
|
|
|
|
function getGoodDevice() {
|
|
var goodConfigs = context.JK.getGoodAudioConfigs();
|
|
if (goodConfigs && goodConfigs.length > 0) {
|
|
deviceId = goodConfigs[0];
|
|
}
|
|
else {
|
|
deviceId = null;
|
|
}
|
|
return deviceId;
|
|
}
|
|
|
|
var deviceId = null;
|
|
|
|
if (preferredDeviceId) {
|
|
|
|
// if the preferred device is not in the list of invalid configs, use it
|
|
if ($.inArray(preferredDeviceId, badConfigs) === -1) {
|
|
deviceId = preferredDeviceId;
|
|
}
|
|
else {
|
|
deviceId = getGoodDevice();
|
|
}
|
|
}
|
|
else {
|
|
deviceId = getGoodDevice();
|
|
}
|
|
return deviceId;
|
|
}
|
|
|
|
context.JK.nowUTC = function() {
|
|
var d = new Date();
|
|
return new Date( d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds() );
|
|
}
|
|
/*
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Copyright (C) Paul Johnston 1999 - 2000.
|
|
* Updated by Greg Holt 2000 - 2001.
|
|
* See http://pajhome.org.uk/site/legal.html for details.
|
|
*/
|
|
|
|
/*
|
|
* Convert a 32-bit number to a hex string with ls-byte first
|
|
*/
|
|
var hex_chr = "0123456789abcdef";
|
|
|
|
function rhex(num) {
|
|
var str, j;
|
|
str = "";
|
|
for (j = 0; j <= 3; j++) {
|
|
str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) +
|
|
hex_chr.charAt((num >> (j * 8)) & 0x0F);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert a string to a sequence of 16-word blocks, stored as an array.
|
|
* Append padding bits and the length, as described in the MD5 standard.
|
|
*/
|
|
function str2blks_MD5(str) {
|
|
var nblk, blks, i;
|
|
nblk = ((str.length + 8) >> 6) + 1;
|
|
blks = new Array(nblk * 16);
|
|
for (i = 0; i < nblk * 16; i++) blks[i] = 0;
|
|
for (i = 0; i < str.length; i++)
|
|
blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8);
|
|
blks[i >> 2] |= 0x80 << ((i % 4) * 8);
|
|
blks[nblk * 16 - 2] = str.length * 8;
|
|
return blks;
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function add(x, y) {
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left
|
|
*/
|
|
function rol(num, cnt) {
|
|
return (num << cnt) | (num >>> (32 - cnt));
|
|
}
|
|
|
|
/*
|
|
* These functions implement the basic operation for each round of the
|
|
* algorithm.
|
|
*/
|
|
function cmn(q, a, b, x, s, t) {
|
|
return add(rol(add(add(a, q), add(x, t)), s), b);
|
|
}
|
|
|
|
function ff(a, b, c, d, x, s, t) {
|
|
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
|
}
|
|
|
|
function gg(a, b, c, d, x, s, t) {
|
|
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
|
}
|
|
|
|
function hh(a, b, c, d, x, s, t) {
|
|
return cmn(b ^ c ^ d, a, b, x, s, t);
|
|
}
|
|
|
|
function ii(a, b, c, d, x, s, t) {
|
|
return cmn(c ^ (b | (~d)), a, b, x, s, t);
|
|
}
|
|
|
|
/*
|
|
* Take a string and return the hex representation of its MD5.
|
|
*/
|
|
context.JK.calcMD5 = function (str) {
|
|
var x, a, b, c, d, i,
|
|
olda, oldb, oldc, oldd;
|
|
x = str2blks_MD5(str);
|
|
a = 1732584193;
|
|
b = -271733879;
|
|
c = -1732584194;
|
|
d = 271733878;
|
|
|
|
for (i = 0; i < x.length; i += 16) {
|
|
olda = a;
|
|
oldb = b;
|
|
oldc = c;
|
|
oldd = d;
|
|
|
|
a = ff(a, b, c, d, x[i + 0], 7, -680876936);
|
|
d = ff(d, a, b, c, x[i + 1], 12, -389564586);
|
|
c = ff(c, d, a, b, x[i + 2], 17, 606105819);
|
|
b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
|
a = ff(a, b, c, d, x[i + 4], 7, -176418897);
|
|
d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
|
c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
|
b = ff(b, c, d, a, x[i + 7], 22, -45705983);
|
|
a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
|
d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
|
c = ff(c, d, a, b, x[i + 10], 17, -42063);
|
|
b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
|
a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
|
d = ff(d, a, b, c, x[i + 13], 12, -40341101);
|
|
c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
|
b = ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
|
|
|
a = gg(a, b, c, d, x[i + 1], 5, -165796510);
|
|
d = gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
|
c = gg(c, d, a, b, x[i + 11], 14, 643717713);
|
|
b = gg(b, c, d, a, x[i + 0], 20, -373897302);
|
|
a = gg(a, b, c, d, x[i + 5], 5, -701558691);
|
|
d = gg(d, a, b, c, x[i + 10], 9, 38016083);
|
|
c = gg(c, d, a, b, x[i + 15], 14, -660478335);
|
|
b = gg(b, c, d, a, x[i + 4], 20, -405537848);
|
|
a = gg(a, b, c, d, x[i + 9], 5, 568446438);
|
|
d = gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
|
c = gg(c, d, a, b, x[i + 3], 14, -187363961);
|
|
b = gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
|
a = gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
|
d = gg(d, a, b, c, x[i + 2], 9, -51403784);
|
|
c = gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
|
b = gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
|
|
|
a = hh(a, b, c, d, x[i + 5], 4, -378558);
|
|
d = hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
|
c = hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
|
b = hh(b, c, d, a, x[i + 14], 23, -35309556);
|
|
a = hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
|
d = hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
|
c = hh(c, d, a, b, x[i + 7], 16, -155497632);
|
|
b = hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
|
a = hh(a, b, c, d, x[i + 13], 4, 681279174);
|
|
d = hh(d, a, b, c, x[i + 0], 11, -358537222);
|
|
c = hh(c, d, a, b, x[i + 3], 16, -722521979);
|
|
b = hh(b, c, d, a, x[i + 6], 23, 76029189);
|
|
a = hh(a, b, c, d, x[i + 9], 4, -640364487);
|
|
d = hh(d, a, b, c, x[i + 12], 11, -421815835);
|
|
c = hh(c, d, a, b, x[i + 15], 16, 530742520);
|
|
b = hh(b, c, d, a, x[i + 2], 23, -995338651);
|
|
|
|
a = ii(a, b, c, d, x[i + 0], 6, -198630844);
|
|
d = ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
|
c = ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
|
b = ii(b, c, d, a, x[i + 5], 21, -57434055);
|
|
a = ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
|
d = ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
|
c = ii(c, d, a, b, x[i + 10], 15, -1051523);
|
|
b = ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
|
a = ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
|
d = ii(d, a, b, c, x[i + 15], 10, -30611744);
|
|
c = ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
|
b = ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
|
a = ii(a, b, c, d, x[i + 4], 6, -145523070);
|
|
d = ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
|
c = ii(c, d, a, b, x[i + 2], 15, 718787259);
|
|
b = ii(b, c, d, a, x[i + 9], 21, -343485551);
|
|
|
|
a = add(a, olda);
|
|
b = add(b, oldb);
|
|
c = add(c, oldc);
|
|
d = add(d, oldd);
|
|
}
|
|
return rhex(a) + rhex(b) + rhex(c) + rhex(d);
|
|
};
|
|
|
|
/** validates that no changes are being made to tracks while recording */
|
|
context.JK.verifyNotRecordingForTrackChange = function (app) {
|
|
if (context.JK.CurrentSessionModel.recordingModel.isRecording()) {
|
|
app.notify({
|
|
title: "Currently Recording",
|
|
text: "Tracks cannot be modified while recording.",
|
|
icon_url: "/assets/content/icon_alert_big.png"});
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
})(window, jQuery); |