diff --git a/app/assets/javascripts/AAC_underscore-min.js b/app/assets/javascripts/AAC_underscore-min.js new file mode 100644 index 000000000..c1d9d3aed --- /dev/null +++ b/app/assets/javascripts/AAC_underscore-min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/app/assets/javascripts/addTrack.js b/app/assets/javascripts/addTrack.js new file mode 100644 index 000000000..08cdfb826 --- /dev/null +++ b/app/assets/javascripts/addTrack.js @@ -0,0 +1,219 @@ +(function(context,$) { + + "use strict"; + + context.JK = context.JK || {}; + context.JK.AddTrackDialog = function(app, myTracks, sessionId, sessionModel) { + var logger = context.JK.logger; + + var myTrackCount = myTracks.length; + + var ASSIGNMENT = { + CHAT: -2, + OUTPUT: -1, + UNASSIGNED: 0, + TRACK1: 1, + TRACK2: 2 + }; + + var VOICE_CHAT = { + CHAT: "0", + SESSION: "1", + MIC: "2" + }; + + var instrument_array = []; + + var instrument_map = { + "Acoustic Guitar": { "client_id": 10, "server_id": "acoustic guitar" }, + "Bass Guitar": { "client_id": 20, "server_id": "bass guitar" }, + "Computer": { "client_id": 30, "server_id": "computer" }, + "Drums": { "client_id": 40, "server_id": "drums" }, + "Electric Guitar": { "client_id": 50, "server_id": "electric guitar" }, + "Keyboard": { "client_id": 60, "server_id": "keyboard" }, + "Voice": { "client_id": 70, "server_id": "voice" }, + "Flute": { "client_id": 80, "server_id": "flute" }, + "Clarinet": { "client_id": 90, "server_id": "clarinet" }, + "Saxophone": { "client_id": 100, "server_id": "saxophone" }, + "Trumpet": { "client_id": 110, "server_id": "trumpet" }, + "Violin": { "client_id": 120, "server_id": "violin" }, + "Trombone": { "client_id": 130, "server_id": "trombone" }, + "Banjo": { "client_id": 140, "server_id": "banjo" }, + "Harmonica": { "client_id": 150, "server_id": "harmonica" }, + "Accordion": { "client_id": 160, "server_id": "accordion" }, + "French Horn": { "client_id": 170, "server_id": "french horn" }, + "Euphonium": { "client_id": 180, "server_id": "euphonium" }, + "Tuba": { "client_id": 190, "server_id": "tuba" }, + "Oboe": { "client_id": 200, "server_id": "oboe" }, + "Ukulele": { "client_id": 210, "server_id": "ukulele" }, + "Cello": { "client_id": 220, "server_id": "cello" }, + "Viola": { "client_id": 230, "server_id": "viola" }, + "Mandolin": { "client_id": 240, "server_id": "mandolin" }, + "Other": { "client_id": 250, "server_id": "other" } + }; + + // dialog variables + var unusedAudioInputChannels = []; + var track2AudioInputChannels = []; + + function events() { + + // Track 2 Add + $('#img-add-track2-input-add').click(function() { + $('#add-track2-unused > option:selected').remove().appendTo('#add-track2-input'); + }); + + // Track 2 Remove + $('#img-add-track2-input-remove').click(function() { + $('#add-track2-input > option:selected').remove().appendTo('#add-track2-unused'); + }); + + $('#btn-cancel-new-audio').click(showOverlay); + $('#btn-error-ok').click(showOverlay); + $('#btn-add-track').click(saveSettings); + + $('#btn-leave-session-test').click(function() { + $('div[layout-id="add-track"]').hide(); + }); + } + + // TODO: figure out how to handle this in layout.js for layered popups + function showOverlay() { + $('.dialog-overlay').show(); + } + + function hideOverlay() { + $('.dialog-overlay').hide(); + } + + function showDialog() { + + $('#add-track2-input').empty(); + $('#add-track2-instrument').empty(); + + initDialogData(); + + // load Unused Inputs + context.JK.loadOptions($('#template-option').html(), $('#add-track2-unused'), unusedAudioInputChannels, "device_id", "name", -1); + + // load Track 2 Input(s) + context.JK.loadOptions($('#template-option').html(), $('#add-track2-input'), track2AudioInputChannels, "device_id", "name", -1); + + // load Track 2 Instrument + context.JK.loadOptions($('#template-option').html(), $('#add-track2-instrument'), instrument_array, "id", "description", -1); + } + + function initDialogData() { + + // clear out arrays + unusedAudioInputChannels = []; + track2AudioInputChannels = []; + + // get data needed for listboxes + var channels = context.jamClient.TrackGetChannels(); + + $.each(channels, function(index, val) { + var assignment = context.jamClient.TrackGetAssignment(val.id, val.input); + logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + assignment + + ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat); + + // INPUT + if (context.jamClient.TrackIsMusicDeviceType(val.device_type)) { + if (val.input) { + if (assignment === ASSIGNMENT.UNASSIGNED) { + if (!val.chat) { + unusedAudioInputChannels.push(val); + } + } + } + } + }); + } + + function saveSettings() { + if (!validateSettings()) { + return; + } + + saveTrack(); + + $('div[layout-id="add-track"]').hide(); + + hideOverlay(); + + // refresh Session screen + sessionModel.refreshCurrentSession(); + } + + function saveTrack() { + // TRACK 2 INPUTS + $("#add-track2-input > option").each(function() { + logger.debug("Saving track 2 input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2); + }); + + // TRACK 2 INSTRUMENT + var instrumentVal = $('#add-track2-instrument').val(); + var instrumentText = $('#add-track2-instrument > option:selected').text().toLowerCase(); + + logger.debug("Saving track 2 instrument = " + instrumentVal); + context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal); + + // UPDATE SERVER + logger.debug("Adding track with instrument " + instrumentText); + var data = {}; + // use the first track's connection_id (not sure why we need this on the track data model) + logger.debug("myTracks[0].connection_id=" + myTracks[0].connection_id); + data.connection_id = myTracks[0].connection_id; + data.instrument_id = instrumentText; + data.sound = "stereo"; + sessionModel.addTrack(sessionId, data); + + context.jamClient.TrackSaveAssignments(); + } + + function validateSettings() { + var isValid = true; + var noTrackErrMsg = 'You must assign at least one input port to each of your tracks. Please update your settings to correct this. If you want to delete a track, please return to the session screen and delete the track by clicking the "x" box in the upper right-hand corner of the track.'; + var noInstrumentErrMsg = 'You must specify what instrument is being played for each track. Please update your settings to correct this.'; + + var errMsg; + + // verify Input and Instrument exist + if ($('#add-track2-input > option').size() === 0 || $('#add-track2-input > option').size() > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + + if (isValid && $('#add-track2-instrument > option:selected').length === 0) { + errMsg = noInstrumentErrMsg; + isValid = false; + } + + if (!isValid) { + context.JK.showErrorDialog(app, errMsg); + } + return isValid; + } + + // TODO: repeated in configureTrack.js + function _init() { + // load instrument array for populating listboxes, using client_id in instrument_map as ID + context.JK.getInstruments(app, function(instruments) { + $.each(instruments, function(index, val) { + instrument_array.push({"id": instrument_map[val.description].client_id, "description": val.description}); + }); + }); + } + + this.initialize = function() { + events(); + _init(); + }; + + this.showDialog = showDialog; + + return this; + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/configureTrack.js b/app/assets/javascripts/configureTrack.js new file mode 100644 index 000000000..d121060b0 --- /dev/null +++ b/app/assets/javascripts/configureTrack.js @@ -0,0 +1,736 @@ +(function(context,$) { + + "use strict"; + + context.JK = context.JK || {}; + context.JK.ConfigureTrackDialog = function(app, myTracks, sessionId, sessionModel) { + var logger = context.JK.logger; + + var myTrackCount = myTracks.length; + + var ASSIGNMENT = { + CHAT: -2, + OUTPUT: -1, + UNASSIGNED: 0, + TRACK1: 1, + TRACK2: 2 + }; + + var VOICE_CHAT = { + CHAT: "0", + SESSION: "1", + MIC: "2" + }; + + var instrument_array = []; + + var instrument_map = { + "Acoustic Guitar": { "client_id": 10, "server_id": "acoustic guitar" }, + "Bass Guitar": { "client_id": 20, "server_id": "bass guitar" }, + "Computer": { "client_id": 30, "server_id": "computer" }, + "Drums": { "client_id": 40, "server_id": "drums" }, + "Electric Guitar": { "client_id": 50, "server_id": "electric guitar" }, + "Keyboard": { "client_id": 60, "server_id": "keyboard" }, + "Voice": { "client_id": 70, "server_id": "voice" }, + "Flute": { "client_id": 80, "server_id": "flute" }, + "Clarinet": { "client_id": 90, "server_id": "clarinet" }, + "Saxophone": { "client_id": 100, "server_id": "saxophone" }, + "Trumpet": { "client_id": 110, "server_id": "trumpet" }, + "Violin": { "client_id": 120, "server_id": "violin" }, + "Trombone": { "client_id": 130, "server_id": "trombone" }, + "Banjo": { "client_id": 140, "server_id": "banjo" }, + "Harmonica": { "client_id": 150, "server_id": "harmonica" }, + "Accordion": { "client_id": 160, "server_id": "accordion" }, + "French Horn": { "client_id": 170, "server_id": "french horn" }, + "Euphonium": { "client_id": 180, "server_id": "euphonium" }, + "Tuba": { "client_id": 190, "server_id": "tuba" }, + "Oboe": { "client_id": 200, "server_id": "oboe" }, + "Ukulele": { "client_id": 210, "server_id": "ukulele" }, + "Cello": { "client_id": 220, "server_id": "cello" }, + "Viola": { "client_id": 230, "server_id": "viola" }, + "Mandolin": { "client_id": 240, "server_id": "mandolin" }, + "Other": { "client_id": 250, "server_id": "other" } + }; + + // dialog variables + var unusedAudioInputChannels = []; + var track1AudioInputChannels = []; + var track2AudioInputChannels = []; + + var unusedAudioOutputChannels = []; + var usedAudioOutputChannels = []; + + var unusedChatInputChannels = []; + var usedChatInputChannels = []; + + var removedAudioChannels = {}; + var removedVoiceChatChannels = {}; + + var devices = []; + var originalDeviceId; + var originalVoiceChat; + var currentVoiceChat; + + var configure_audio_instructions = { + "Win32": "Choose the driver to use for audio and check its settings. Then use arrow " + + "buttons to assign audio inputs to your tracks, to indicate what instrument you are playing on " + + "each track, and to assign audio outputs for listening. If you don't see an audio device you think " + + "should be listed, view this help topic to understand why.", + + "MacOSX": "Use arrow buttons to assign audio inputs to your tracks, to indicate what " + + "instrument you are playing on each track, and to assign audio outputs for listening. If you don't " + + "see an audio device you think should be listed, view this help topic to understand why.", + + "Unix": "Use arrow buttons to assign audio inputs to your tracks, to indicate what " + + "instrument you are playing on each track, and to assign audio outputs for listening. If you don't " + + "see an audio device you think should be listed, view this help topic to understand why." + }; + + var configure_voice_instructions = "If you are using a microphone to capture your instrumental or vocal audio, you can simply use that mic " + + "for both music and chat. Otherwise, choose a device to use for voice chat, and use arrow buttons to " + + "select an input on that device."; + + function toggleTrack2ConfigDetails(visible) { + if (visible) { + $('#track2-arrows-div').show(); + $('#track2-input-div').show(); + $('#track2-instrument-div').show(); + + $('#track1-input').height('70px'); + $('#track1-instrument').height('70px'); + } + else { + $('#track2-arrows-div').hide(); + $('#track2-input-div').hide(); + $('#track2-instrument-div').hide(); + + $('#track1-input').height('145px'); + $('#track1-instrument').height('145px'); + } + } + + function events() { + $('#tab-configure-audio').click(function() { + // validate voice chat settings + if (validateVoiceChatSettings(true)) { + showMusicAudioPanel(false); + } + }); + + $('#tab-configure-voice').click(function() { + // validate audio settings + if (validateAudioSettings(true)) { + showVoiceChatPanel(false); + } + }); + + // Track 1 Add + $('#img-track1-input-add').click(function() { + // REMOVE FROM VOICE CHAT UNUSED IF NECESSARY + syncVoiceChatDialog(); + $('#audio-inputs-unused > option:selected').remove().appendTo('#track1-input'); + }); + + // Track 1 Remove + $('#img-track1-input-remove').click(function() { + // ADD TO VOICE CHAT UNUSED IF NECESSARY + $("#track1-input > option:selected").each(function() { + var deviceId = this.value; + var description = this.text; + if ($('#track1-input > option[value="' + deviceId + '"]').length > 0) { + if (removedVoiceChatChannels[deviceId]) { + restoreVoiceChatOptions(deviceId); + } + } + $(this).remove().appendTo('#audio-inputs-unused'); + }); + }); + + // Track 2 Add + $('#img-track2-input-add').click(function() { + // REMOVE FROM VOICE CHAT UNUSED IF NECESSARY + syncVoiceChatDialog(); + $('#audio-inputs-unused > option:selected').remove().appendTo('#track2-input'); + }); + + // Track 2 Remove + $('#img-track2-input-remove').click(function() { + // ADD TO VOICE CHAT UNUSED IF NECESSARY + $("#track2-input > option:selected").each(function() { + var deviceId = this.value; + var description = this.text; + if ($('#track2-input > option[value="' + deviceId + '"]').length > 0) { + restoreVoiceChatOptions(deviceId); + } + $(this).remove().appendTo('#audio-inputs-unused'); + }); + }); + + // Audio Output Add + $('#img-audio-output-add').click(function() { + $('#audio-output-unused > option:selected').remove().appendTo('#audio-output-selection'); + }); + + // Audio Output Remove + $('#img-audio-output-remove').click(function() { + $('#audio-output-selection > option:selected').remove().appendTo('#audio-output-unused'); + }); + + // Voice Chat Add + $('#img-voice-input-add').click(function() { + // REMOVE FROM AUDIO UNUSED IF NECESSARY + syncMusicAudioDialog(); + $('#voice-inputs-unused > option:selected').remove().appendTo('#voice-inputs-selection'); + }); + + $('#img-voice-input-remove').click(function() { + // ADD TO AUDIO UNUSED IF NECESSARY + $("#voice-inputs-selection > option:selected").each(function() { + var deviceId = this.value; + var description = this.text; + if ($('#voice-inputs-selection > option[value="' + deviceId + '"]').length > 0) { + if (removedAudioChannels[deviceId]) { + logger.debug("Adding " + deviceId + " to Music Audio Unused"); + var option = ''; + $('#audio-inputs-unused').append(option); + delete removedAudioChannels[deviceId]; + } + $('#voice-inputs-unused > option[value="' + deviceId + '"]').remove(); + } + $(this).remove().appendTo('#voice-inputs-unused'); + }); + }); + + $('.voicechat-settings').click(function() { + // call this to initialize Music Audio tab + showMusicAudioPanel(true); + showVoiceChatPanel(true); + }); + + $('#audio-drivers').change(function() { + audioDriverChanged(); + }); + + $('#voice-chat-device').change(function() { + voiceChatChanged(); + }); + + $('#btn-driver-settings').click(function() { + logger.debug("Opening control panel..."); + context.jamClient.TrackOpenControlPanel(); + }); + + $('#btn-cancel-new-audio').click(showOverlay); + $('#btn-error-ok').click(showOverlay); + $('#btn-save-settings').click(saveSettings); + $('#btn-cancel-settings').click(cancelSettings); + + $('#btn-leave-session-test').click(function() { + $('div[layout-id="configure-audio"]').hide(); + }); + } + + function restoreVoiceChatOptions(deviceId) { + logger.debug("Adding " + deviceId + " to Voice Chat Unused"); + $('#voice-inputs-unused').append(removedVoiceChatChannels[deviceId]); + delete removedVoiceChatChannels[deviceId]; + syncVoiceChatDialog(); + } + + function syncVoiceChatDialog() { + $("#audio-inputs-unused option:selected").each(function() { + var deviceId = this.value; + var description = this.text; + + if ($('#voice-inputs-unused > option[value="' + deviceId + '"]').length > 0) { + logger.debug("Removing " + deviceId + " from Voice Chat Unused"); + + $('#voice-inputs-unused > option[value="' + deviceId + '"]').remove(); + var option = ''; + removedVoiceChatChannels[deviceId] = option; + } + }); + + // remove Session Audio option from voice chat if none are available + if ($('#voice-inputs-unused > option').size() === 0) { + logger.debug('Removing Option 1 from Voice Chat dropdown.'); + $('#voice-chat-device > option[value="1"]').remove(); + } + else { + if ($('#voice-chat-device > option[value="1"]').length === 0) { + logger.debug('Adding Option 1 back to Voice Chat dropdown.'); + $('#voice-chat-device').prepend(''); + } + } + } + + function syncMusicAudioDialog() { + $("#voice-inputs-unused > option:selected").each(function() { + var deviceId = this.value; + var description = this.text; + + if ($('#audio-inputs-unused > option[value="' + deviceId + '"]').length > 0) { + logger.debug("Removing " + deviceId + " from Music Audio Unused"); + + $('#audio-inputs-unused > option[value="' + deviceId + '"]').remove(); + var option = ''; + removedAudioChannels[deviceId] = option; + } + }); + } + + // TODO: figure out how to handle this in layout.js for layered popups + function showOverlay() { + $('.dialog-overlay').show(); + } + + function hideOverlay() { + $('.dialog-overlay').hide(); + } + + function audioDriverChanged() { + // ensure any channels removed are restored + var keys = Object.keys(removedVoiceChatChannels); + for (var i=0; i < keys.length; i++) { + restoreVoiceChatOptions(keys[i]); + } + + context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); + + // refresh dialog + showMusicAudioPanel(true); + } + + function voiceChatChanged() { + // ensure any channels removed are restored + var keys = Object.keys(removedAudioChannels); + for (var i=0; i < keys.length; i++) { + $('#audio-inputs-unused').append(removedAudioChannels[keys[i]]); + delete removedAudioChannels[keys[i]]; + } + + showVoiceChatPanel(true); + } + + function configureDriverSettingsButton() { + if (context.jamClient.TrackHasControlPanel()) { + logger.debug("Showing DRIVER SETTINGS button..."); + $('#btn-driver-settings').show(); + } + else { + logger.debug("Hiding DRIVER SETTINGS button..."); + $('#btn-driver-settings').hide(); + } + } + + function showMusicAudioPanel(refreshLists) { + + _setInstructions('audio'); + + $('div[tab-id="music-audio"]').show(); + $('div[tab-id="voice-chat"]').hide(); + + $('#tab-configure-audio').addClass('selected'); + $('#tab-configure-voice').removeClass('selected'); + + if (refreshLists) { + configureDriverSettingsButton(); + + $('#audio-drivers').empty(); + + // determine correct music device to preselect + var deviceId = context.jamClient.TrackGetMusicDeviceID(); + logger.debug("deviceId = " + deviceId); + + // load Audio Driver dropdown + devices = context.jamClient.TrackGetDevices(); + var keys = Object.keys(devices); + + for (var i=0; i < keys.length; i++) { + var template = $('#template-option').html(); + var isSelected = ""; + if (keys[i] === deviceId) { + isSelected = "selected"; + } + var html = context.JK.fillTemplate(template, { + value: keys[i], + label: devices[keys[i]], + selected: isSelected + }); + + $('#audio-drivers').append(html); + } + + $('#audio-inputs-unused').empty(); + $('#track1-input').empty(); + $('#track1-instrument').empty(); + $('#track2-input').empty(); + $('#track2-instrument').empty(); + $('#audio-output-unused').empty(); + $('#audio-output-selection').empty(); + + initDialogData(); + + // filter out any channels already used on the Voice Chat tab + var musicAudioOptions = []; + $.each(unusedAudioInputChannels, function(index, val) { + var deviceId = val.device_id; + // verify the device is not already used on track 1 or 2 + if ($('#voice-inputs-selection > option[value="' + deviceId + '"]').length === 0) { + logger.debug("Adding " + val.device_id + " to Music Audio."); + musicAudioOptions.push(val); + } + }); + + // load Unused Inputs + context.JK.loadOptions($('#template-option').html(), $('#audio-inputs-unused'), musicAudioOptions, "device_id", "name", -1); + + // load Track 1 Input(s) + context.JK.loadOptions($('#template-option').html(), $('#track1-input'), track1AudioInputChannels, "device_id", "name", -1); + + // load Track 1 Instrument + var current_instrument = context.jamClient.TrackGetInstrument(1); + context.JK.loadOptions($('#template-option').html(), $('#track1-instrument'), instrument_array, "id", "description", current_instrument); + + // load Track 2 config details if necessary + if (myTrackCount > 1) { + // load Track 2 Input(s) + context.JK.loadOptions($('#template-option').html(), $('#track2-input'), track2AudioInputChannels, "device_id", "name", -1); + + // load Track 2 Instrument + current_instrument = context.jamClient.TrackGetInstrument(2); + context.JK.loadOptions($('#template-option').html(), $('#track2-instrument'), instrument_array, "id", "description", current_instrument); + } + + // load Unused Outputs + context.JK.loadOptions($('#template-option').html(), $('#audio-output-unused'), unusedAudioOutputChannels, "device_id", "name", -1); + + // load Session Audio Output + context.JK.loadOptions($('#template-option').html(), $('#audio-output-selection'), usedAudioOutputChannels, "device_id", "name", -1); + } + } + + function showVoiceChatPanel(refreshLists) { + _setInstructions('voice'); + + $('div[tab-id="music-audio"]').hide(); + $('div[tab-id="voice-chat"]').show(); + + $('#tab-configure-audio').removeClass('selected'); + $('#tab-configure-voice').addClass('selected'); + + if (refreshLists) { + $('#voice-inputs-unused').empty(); + $('#voice-inputs-selection').empty(); + + initDialogData(); + + var chatOption = $('#voice-chat-device').val(); + + // populate with unused session inputs + var voiceChatOptions = []; + $.each(unusedAudioInputChannels, function(index, val) { + var deviceId = val.device_id; + // verify the device is not already used on track 1 or 2 + if ($('#track1-input > option[value="' + deviceId + '"]').length === 0 && + $('#track2-input > option[value="' + deviceId + '"]').length === 0) { + voiceChatOptions.push(val); + } + }); + + if (chatOption === VOICE_CHAT.SESSION) { + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), voiceChatOptions, "device_id", "name", -1); + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), usedChatInputChannels, "device_id", "name", -1); + } + + // populate with voice devices + else if (chatOption === VOICE_CHAT.CHAT) { + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), unusedChatInputChannels, "device_id", "name", -1); + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), usedChatInputChannels, "device_id", "name", -1); + } + + // disable inputs + else if (chatOption === VOICE_CHAT.MIC) { + + } + } + } + + function initDialogData() { + + // clear out arrays + unusedAudioInputChannels = []; + track1AudioInputChannels = []; + track2AudioInputChannels = []; + + unusedAudioOutputChannels = []; + usedAudioOutputChannels = []; + + unusedChatInputChannels = []; + usedChatInputChannels = []; + + // get data needed for listboxes + var channels = context.jamClient.TrackGetChannels(); + + $.each(channels, function(index, val) { + var assignment = context.jamClient.TrackGetAssignment(val.id, val.input); + logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + assignment + + ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat); + + // INPUT + if (context.jamClient.TrackIsMusicDeviceType(val.device_type)) { + if (val.input) { + if (assignment === ASSIGNMENT.CHAT) { + usedChatInputChannels.push(val); + } + else if (assignment === ASSIGNMENT.UNASSIGNED) { + if (!val.chat) { + unusedAudioInputChannels.push(val); + } + else { + unusedChatInputChannels.push(val); + } + } + else if (assignment === ASSIGNMENT.OUTPUT) { + + } + else { + if (assignment === ASSIGNMENT.TRACK1) { + track1AudioInputChannels.push(val); + } + else if (assignment === ASSIGNMENT.TRACK2) { + track2AudioInputChannels.push(val); + } + } + } + + // OUTPUT + else { + if (assignment === ASSIGNMENT.CHAT) { + + } + else if (assignment === ASSIGNMENT.UNASSIGNED) { + if (!val.chat) { + unusedAudioOutputChannels.push(val); + } + } + else if (assignment === ASSIGNMENT.OUTPUT) { + + } + else { + } + } + } + }); + } + + function saveSettings() { + if (!validateAudioSettings(false)) { + return; + } + + if (!validateVoiceChatSettings(false)) { + return; + } + + saveAudioSettings(); + saveVoiceChatSettings(); + + originalDeviceId = $('#audio-drivers').val(); + $('div[layout-id="configure-audio"]').hide(); + + hideOverlay(); + + // refresh Session screen + sessionModel.refreshCurrentSession(); + } + + function saveAudioSettings() { + + // TRACK 1 INPUTS + $("#track1-input > option").each(function() { + logger.debug("Saving track 1 input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1); + }); + + // TRACK 1 INSTRUMENT + var instrumentVal = $('#track1-instrument').val(); + var instrumentText = $('#track1-instrument > option:selected').text().toLowerCase(); + + logger.debug("Saving track 1 instrument = " + instrumentVal); + context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal); + + // UPDATE SERVER + logger.debug("Updating track " + myTracks[0].trackId + " with instrument " + instrumentText); + var data = {}; + data.instrument_id = instrumentText; + sessionModel.updateTrack(sessionId, myTracks[0].trackId, data); + + if (myTrackCount > 1) { + // TRACK 2 INPUTS + $("#track2-input > option").each(function() { + logger.debug("Saving track 2 input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2); + }); + + // TRACK 2 INSTRUMENT + instrumentVal = $('#track2-instrument').val(); + instrumentText = $('#track2-instrument > option:selected').text().toLowerCase(); + + logger.debug("Saving track 2 instrument = " + instrumentVal); + context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal); + + // UPDATE SERVER + logger.debug("Updating track " + myTracks[1].trackId + " with instrument " + instrumentText); + data.instrument_id = instrumentText; + sessionModel.updateTrack(myTracks[1].trackId, sessionId, data); + } + + // OUTPUT + $("#audio-output-selection > option").each(function() { + logger.debug("Saving session audio output = " + this.value); + context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT); + }); + + context.jamClient.TrackSaveAssignments(); + } + + function saveVoiceChatSettings() { + currentVoiceChat = $('#voice-chat-device').val(); + + logger.debug("Calling TrackSetChatUsesMusic with value = " + currentVoiceChat); + context.jamClient.TrackSetChatUsesMusic(currentVoiceChat); + + $("#voice-inputs-selection > option").each(function() { + logger.debug("Saving chat input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT); + }); + } + + function cancelSettings() { + // reset to original device ID + context.jamClient.TrackSetMusicDevice(originalDeviceId); + + // reset voice chat option to original + $('#voice-chat-device').val(originalVoiceChat); + } + + function validateAudioSettings(allowEmptyInput) { + var isValid = true; + var noTrackErrMsg = 'You must assign at least one input port to each of your tracks. Please update your settings to correct this. If you want to delete a track, please return to the session screen and delete the track by clicking the "x" box in the upper right-hand corner of the track.'; + var noInstrumentErrMsg = 'You must specify what instrument is being played for each track. Please update your settings to correct this.'; + var outputErrMsg = 'You must assign two output ports for stereo session audio to hear music. Please update your settings to correct this.'; + + var errMsg; + + // if there are no inputs remaining then allow the user to switch to the Voice Chat tab + // to remove some + if (allowEmptyInput && $('#audio-inputs-unused > option').size() === 0) { + return isValid; + } + else { + // verify Track 1 Input and Instrument exist + if ($('#track1-input > option').size() === 0 || $('#track1-input > option').size() > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + + if (isValid) { + if ($('#track1-instrument > option:selected').length === 0) { + errMsg = noInstrumentErrMsg; + isValid = false; + } + } + + // if Track 2 exists, verify Input and Instrument exist + if (isValid && myTrackCount > 1) { + if ($('#track2-input > option').size() === 0 || $('#track2-input > option').size() > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + + if (isValid && $('#track2-instrument > option:selected').length === 0) { + errMsg = noInstrumentErrMsg; + isValid = false; + } + } + + // verify Session Audio Output exists + if (isValid && $('#audio-output-selection > option').size() !== 2) { + errMsg = outputErrMsg; + isValid = false; + } + + if (!isValid) { + context.JK.showErrorDialog(app, errMsg); + } + } + + return isValid; + } + + function validateVoiceChatSettings(allowEmptyInput) { + var isValid = true; + var noTrackErrMsg = 'You must select a voice input.'; + var errMsg; + + if (allowEmptyInput && $('#voice-inputs-unused > option').size() === 0) { + return isValid; + } + else { + currentVoiceChat = $('#voice-chat-device').val(); + if (currentVoiceChat === VOICE_CHAT.SESSION || currentVoiceChat === VOICE_CHAT.CHAT) { + if ($('#voice-inputs-selection > option').size() === 0 || $('#voice-inputs-selection > option').size() > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + } + else if (currentVoiceChat === VOICE_CHAT.MIC) { + // NO VALIDATION NEEDED + } + + if (!isValid) { + context.JK.showErrorDialog(app, errMsg); + } + } + + return isValid; + } + + function _setInstructions(type) { + if (type === 'audio') { + var os = context.jamClient.GetOSAsString(); + $('#instructions', 'div[layout-id="configure-audio"]').html(configure_audio_instructions[os]); + } + else if (type === 'voice') { + $('#instructions', 'div[layout-id="configure-audio"]').html(configure_voice_instructions); + } + } + + function _init() { + // load instrument array for populating listboxes, using client_id in instrument_map as ID + context.JK.getInstruments(app, function(instruments) { + $.each(instruments, function(index, val) { + instrument_array.push({"id": instrument_map[val.description].client_id, "description": val.description}); + }); + }); + + originalVoiceChat = context.jamClient.TrackGetChatUsesMusic(); + $('#voice-chat-device').val(originalVoiceChat); + + originalDeviceId = context.jamClient.TrackGetMusicDeviceID(); + } + + this.initialize = function() { + events(); + _init(); + toggleTrack2ConfigDetails(myTrackCount > 1); + }; + + this.showMusicAudioPanel = showMusicAudioPanel; + this.showVoiceChatPanel = showVoiceChatPanel; + + return this; + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/fakeJamClient.js b/app/assets/javascripts/fakeJamClient.js index c1d114e84..b27eafc48 100644 --- a/app/assets/javascripts/fakeJamClient.js +++ b/app/assets/javascripts/fakeJamClient.js @@ -200,14 +200,14 @@ // But we'll just build a list of names and fake it var devices = [ - "M-Audio FW Audiophile: FW AP 1/2", + "M-Audio FW Audiophile: FW AP 1/2" //"M-Audio FW Audiophile: FW Multi 1/2", //"M-Audio FW Audiophile: FW SPDIF 1/2", - "Realtek High Definition Audio: Realtek HD Digital", + //"Realtek High Definition Audio: Realtek HD Digital", // "Realtek High Definition Audio: Realtek HD Line", // "Realtek High Definition Audio: Realtek HD Audio Mic", // "Realtek High Definition Audio: Realtek HD Audio Stereo", - "WebCamDV WDM Audio Capture: WebCamDV Audio" + //"WebCamDV WDM Audio Capture: WebCamDV Audio" ]; var suffixes = [ " - Left", " - Right", " - Left", " - Right"]; var lefts = [true, false, true, false]; diff --git a/app/assets/javascripts/homeScreen.js b/app/assets/javascripts/homeScreen.js index a9d22583a..f6d9fad2a 100644 --- a/app/assets/javascripts/homeScreen.js +++ b/app/assets/javascripts/homeScreen.js @@ -3,6 +3,7 @@ "use strict"; context.JK = context.JK || {}; + var logger = context.JK.logger; context.JK.HomeScreen = function(app) { function events() { @@ -12,6 +13,9 @@ $('.homecard').on('mouseleave', function() { $(this).removeClass('hover'); }); + $('.profile').on('click', function() { + context.location = '#/profile/' + context.JK.currentUserId; + }) } this.initialize = function() { diff --git a/app/assets/javascripts/jam_rest.js b/app/assets/javascripts/jam_rest.js index f93ad917e..32ea7c13b 100644 --- a/app/assets/javascripts/jam_rest.js +++ b/app/assets/javascripts/jam_rest.js @@ -90,11 +90,11 @@ this.getCities = getCities; this.getRegions = getRegions; this.getIsps = getIsps; - this.getInstruments = getInstruments this.getPhotoUrl = getPhotoUrl; + //this.getInstruments = getInstruments return this; }; -})(window,jQuery); \ No newline at end of file +})(window,jQuery); diff --git a/app/assets/javascripts/jamkazam.js b/app/assets/javascripts/jamkazam.js index 9285e3615..dc5549eee 100644 --- a/app/assets/javascripts/jamkazam.js +++ b/app/assets/javascripts/jamkazam.js @@ -2,6 +2,18 @@ "use strict"; + // Change underscore's default templating characters as they + // conflict withe the ERB rendering. Templates will use: + // {{ interpolate }} + // {% evaluate %} + // {{- escape }} + // + context._.templateSettings = { + evaluate : /\{%([\s\S]+?)%\}/g, + interpolate : /\{\{([\s\S]+?)\}\}/g, + escape : /\{\{-([\s\S]+?)\}\}/g + }; + context.JK = context.JK || {}; var JamKazam = context.JK.JamKazam = function() { diff --git a/app/assets/javascripts/session.js b/app/assets/javascripts/session.js index 5772ac078..610d05285 100644 --- a/app/assets/javascripts/session.js +++ b/app/assets/javascripts/session.js @@ -10,69 +10,9 @@ var tracks = {}; var myTracks = []; var mixers = []; - var myTrackCount = 0; - var ASSIGNMENT = { - CHAT: -2, - OUTPUT: -1, - UNASSIGNED: 0, - TRACK1: 1, - TRACK2: 2 - }; - - var VOICE_CHAT = { - CHAT: "0", - SESSION: "1", - MIC: "2" - }; - - var instrument_array = []; - - var instrument_map = { - "Acoustic Guitar": { "client_id": 10, "server_id": "acoustic guitar" }, - "Bass Guitar": { "client_id": 20, "server_id": "bass guitar" }, - "Computer": { "client_id": 30, "server_id": "computer" }, - "Drums": { "client_id": 40, "server_id": "drums" }, - "Electric Guitar": { "client_id": 50, "server_id": "electric guitar" }, - "Keyboard": { "client_id": 60, "server_id": "keyboard" }, - "Voice": { "client_id": 70, "server_id": "voice" }, - "Flute": { "client_id": 80, "server_id": "flute" }, - "Clarinet": { "client_id": 90, "server_id": "clarinet" }, - "Saxophone": { "client_id": 100, "server_id": "saxophone" }, - "Trumpet": { "client_id": 110, "server_id": "trumpet" }, - "Violin": { "client_id": 120, "server_id": "violin" }, - "Trombone": { "client_id": 130, "server_id": "trombone" }, - "Banjo": { "client_id": 140, "server_id": "banjo" }, - "Harmonica": { "client_id": 150, "server_id": "harmonica" }, - "Accordion": { "client_id": 160, "server_id": "accordion" }, - "French Horn": { "client_id": 170, "server_id": "french horn" }, - "Euphonium": { "client_id": 180, "server_id": "euphonium" }, - "Tuba": { "client_id": 190, "server_id": "tuba" }, - "Oboe": { "client_id": 200, "server_id": "oboe" }, - "Ukulele": { "client_id": 210, "server_id": "ukulele" }, - "Cello": { "client_id": 220, "server_id": "cello" }, - "Viola": { "client_id": 230, "server_id": "viola" }, - "Mandolin": { "client_id": 240, "server_id": "mandolin" } - }; - - // dialog variables - var unusedAudioInputChannels = []; - var track1AudioInputChannels = []; - var track2AudioInputChannels = []; - - var unusedAudioOutputChannels = []; - var usedAudioOutputChannels = []; - - var unusedChatInputChannels = []; - var usedChatInputChannels = []; - - var removedAudioChannels = {}; - var removedVoiceChatChannels = {}; - - var devices = []; - var originalDeviceId; - var originalVoiceChat; - var currentVoiceChat; + var configureTrackDialog; + var addTrackDialog; // TODO Consolidate dragged controls and handles var $draggingFaderHandle = null; @@ -89,25 +29,6 @@ var lookingForMixersTimer = null; var lookingForMixers = {}; - var configure_audio_instructions = { - "Win32": "Choose the driver to use for audio and check its settings. Then use arrow " + - "buttons to assign audio inputs to your tracks, to indicate what instrument you are playing on " + - "each track, and to assign audio outputs for listening. If you don't see an audio device you think " + - "should be listed, view this help topic to understand why.", - - "MacOSX": "Use arrow buttons to assign audio inputs to your tracks, to indicate what " + - "instrument you are playing on each track, and to assign audio outputs for listening. If you don't " + - "see an audio device you think should be listed, view this help topic to understand why.", - - "Unix": "Use arrow buttons to assign audio inputs to your tracks, to indicate what " + - "instrument you are playing on each track, and to assign audio outputs for listening. If you don't " + - "see an audio device you think should be listed, view this help topic to understand why." - }; - - var configure_voice_instructions = "If you are using a microphone to capture your instrumental or vocal audio, you can simply use that mic " + - "for both music and chat. Otherwise, choose a device to use for voice chat, and use arrow buttons to " + - "select an input on that device."; - var defaultParticipant = { tracks: [{ instrument_id: "unknown" @@ -157,18 +78,6 @@ } } checkForCurrentUser(); - - // load instrument array for populating listboxes, using client_id in instrument_map as ID - var instruments = context.JK.getInstruments(app, function(instruments) { - $.each(instruments, function(index, val) { - instrument_array.push({"id": instrument_map[val.description].client_id, "description": val.description}); - }); - }); - - originalVoiceChat = context.jamClient.TrackGetChatUsesMusic(); - $('#voice-chat-device').val(originalVoiceChat); - - originalDeviceId = context.jamClient.TrackGetMusicDeviceID(); } function afterCurrentUserLoaded() { @@ -199,8 +108,12 @@ _wireTopVolume(); _wireTopMix(); _addVoiceChat(); + _initDialogs(); + } - toggleTrack2ConfigDetails(myTrackCount > 1); + function _initDialogs() { + configureTrackDialog.initialize(); + addTrackDialog.initialize(); } // Get the latest list of underlying audio mixer channels @@ -291,7 +204,6 @@ function _renderTracks() { myTracks = []; - myTrackCount = 0; // Participants are here now, but the mixers don't update right away. // Draw tracks from participants, then setup timers to look for the @@ -314,6 +226,7 @@ // Default trackData to participant + no Mixer state. var trackData = { trackId: track.id, + connection_id: track.connection_id, clientId: participant.client_id, name: name, instrumentIcon: instrumentIcon, @@ -348,35 +261,30 @@ lookingForMixersTimer = context.setInterval(lookForMixers, 300); } } - _addTrack(trackData); + _addTrack(index, trackData); + // Show settings icons only for my tracks if (myTrack) { $('div[mixer-id="' + mixer.id + '"].track-icon-settings').show(); - // myTrackCount++; // myTracks.push(trackData); } - myTrackCount++; + // TODO: FIX THIS myTracks.push(trackData); }); }); - } - function toggleTrack2ConfigDetails(visible) { - if (visible) { - $('#track2-arrows-div').show(); - $('#track2-input-div').show(); - $('#track2-instrument-div').show(); + configureTrackDialog = new context.JK.ConfigureTrackDialog(app, myTracks, sessionId, sessionModel); + addTrackDialog = new context.JK.AddTrackDialog(app, myTracks, sessionId, sessionModel); - $('#track1-input').height('70px'); - $('#track1-instrument').height('70px'); + // hide "Add Track" link if there are 2 tracks + if (myTracks.length === 2) { + $('#div-add-track').hide(); } else { - $('#track2-arrows-div').hide(); - $('#track2-input-div').hide(); - $('#track2-instrument-div').hide(); - - $('#track1-input').height('145px'); - $('#track1-instrument').height('145px'); + $('#div-add-track').show(); + $('#div-add-track').click(function() { + addTrackDialog.showDialog(); + }); } } @@ -461,7 +369,7 @@ } } - function _addTrack(trackData) { + function _addTrack(index, trackData) { var $destination = $('#session-mytracks-container'); if (trackData.clientId !== app.clientId) { $destination = $('#session-livetracks-container'); @@ -471,10 +379,19 @@ var template = $('#template-session-track').html(); var newTrack = context.JK.fillTemplate(template, trackData); $destination.append(newTrack); + + var $closeButton = $('#div-track-close', 'div[track-id="' + trackData.trackId + '"]'); + if (index === 0) { + $closeButton.hide(); + } + else { + $closeButton.click(deleteTrack); + } + $('div[mixer-id="' + trackData.mixerId + '"].track-icon-settings').click(function() { // call this to initialize Voice Chat tab - showVoiceChatPanel(true); - showMusicAudioPanel(true); + configureTrackDialog.showVoiceChatPanel(true); + configureTrackDialog.showMusicAudioPanel(true); }); tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId); } @@ -531,6 +448,11 @@ } } + function deleteTrack(evt) { + var trackId = $(evt.currentTarget).attr("track-id"); + sessionModel.deleteTrack(trackId); + } + function _toggleVisualMuteControl($control, muting) { if (muting) { $control.removeClass('enabled'); @@ -762,594 +684,11 @@ $('#voice-chat').on('mousemove', faderMouseMove); $('body').on('mouseup', faderMouseUp); - $('#tab-configure-audio').click(function() { - // validate voice chat settings - if (validateVoiceChatSettings()) { - showMusicAudioPanel(false); - } - }); - - $('#tab-configure-voice').click(function() { - // validate audio settings - if (validateAudioSettings()) { - showVoiceChatPanel(false); - } - }); - - // Track 1 Add - $('#img-track1-input-add').click(function() { - // REMOVE FROM VOICE CHAT UNUSED IF NECESSARY - syncVoiceChatDialog(); - $('#audio-inputs-unused > option:selected').remove().appendTo('#track1-input'); - }); - - // Track 1 Remove - $('#img-track1-input-remove').click(function() { - // ADD TO VOICE CHAT UNUSED IF NECESSARY - $("#track1-input > option:selected").each(function() { - var deviceId = this.value; - var description = this.text; - if ($('#track1-input > option[value="' + deviceId + '"]').length > 0) { - if (removedVoiceChatChannels[deviceId]) { - logger.debug("Adding " + deviceId + " to Voice Chat Unused"); - $('#voice-inputs-unused').append(''); - delete removedVoiceChatChannels[deviceId]; - } - } - $(this).remove().appendTo('#audio-inputs-unused'); - }); - }); - - // Track 2 Add - $('#img-track2-input-add').click(function() { - // REMOVE FROM VOICE CHAT UNUSED IF NECESSARY - syncVoiceChatDialog(); - $('#audio-inputs-unused > option:selected').remove().appendTo('#track2-input'); - }); - - // Track 2 Remove - $('#img-track2-input-remove').click(function() { - // ADD TO VOICE CHAT UNUSED IF NECESSARY - $("#track2-input > option:selected").each(function() { - var deviceId = this.value; - var description = this.text; - if ($('#track2-input > option[value="' + deviceId + '"]').length > 0) { - if (removedVoiceChatChannels[deviceId]) { - logger.debug("Adding " + deviceId + " to Voice Chat Unused"); - $('#voice-inputs-unused').append(''); - delete removedVoiceChatChannels[deviceId]; - } - } - $(this).remove().appendTo('#audio-inputs-unused'); - }); - }); - - // Audio Output Add - $('#img-audio-output-add').click(function() { - $('#audio-output-unused > option:selected').remove().appendTo('#audio-output-selection'); - }); - - // Audio Output Remove - $('#img-audio-output-remove').click(function() { - $('#audio-output-selection > option:selected').remove().appendTo('#audio-output-unused'); - }); - - // Voice Chat Add - $('#img-voice-input-add').click(function() { - // REMOVE FROM AUDIO UNUSED IF NECESSARY - syncMusicAudioDialog(); - $('#voice-inputs-unused > option:selected').remove().appendTo('#voice-inputs-selection'); - }); - - $('#img-voice-input-remove').click(function() { - // ADD TO AUDIO UNUSED IF NECESSARY - $("#voice-inputs-selection > option:selected").each(function() { - var deviceId = this.value; - var description = this.text; - if ($('#voice-inputs-selection > option[value="' + deviceId + '"]').length > 0) { - if (removedAudioChannels[deviceId]) { - logger.debug("Adding " + deviceId + " to Music Audio Unused"); - var option = ''; - $('#audio-inputs-unused').append(option); - delete removedAudioChannels[deviceId]; - } - $('#voice-inputs-unused > option[value="' + deviceId + '"]').remove(); - } - $(this).remove().appendTo('#voice-inputs-unused'); - }); - }); - $('.voicechat-settings').click(function() { // call this to initialize Music Audio tab - showMusicAudioPanel(true); - showVoiceChatPanel(true); + configureTrackDialog.showMusicAudioPanel(true); + configureTrackDialog.showVoiceChatPanel(true); }); - - $('#audio-drivers').change(function() { - audioDriverChanged(); - }); - - $('#voice-chat-device').change(function() { - voiceChatChanged(); - }); - - $('#btn-driver-settings').click(function() { - logger.debug("Opening control panel..."); - context.jamClient.TrackOpenControlPanel(); - }); - - $('#btn-cancel-new-audio').click(showOverlay); - $('#btn-error-ok').click(showOverlay); - $('#btn-save-settings').click(saveSettings); - $('#btn-cancel-settings').click(cancelSettings); - - $('#btn-leave-session-test').click(function() { - $('div[layout-id="configure-audio"]').hide(); - }); - } - - function syncVoiceChatDialog() { - $("#audio-inputs-unused option:selected").each(function() { - var deviceId = this.value; - var description = this.text; - - if ($('#voice-inputs-unused > option[value="' + deviceId + '"]').length > 0) { - logger.debug("Removing " + deviceId + " from Voice Chat Unused"); - - $('#voice-inputs-unused > option[value="' + deviceId + '"]').remove(); - var option = ''; - removedVoiceChatChannels[deviceId] = option; - - // TODO: ADD THIS BACK WHEN APPROPRIATE - if ($('#voice-inputs-unused > option').size() === 0) { - $('#voice-chat-device > option[value="1"]').remove(); - } - } - }); - } - - function syncMusicAudioDialog() { - $("#voice-inputs-unused > option:selected").each(function() { - var deviceId = this.value; - var description = this.text; - - if ($('#audio-inputs-unused > option[value="' + deviceId + '"]').length > 0) { - logger.debug("Removing " + deviceId + " from Music Audio Unused"); - - $('#audio-inputs-unused > option[value="' + deviceId + '"]').remove(); - var option = ''; - removedAudioChannels[deviceId] = option; - } - }); - } - - // TODO: figure out how to handle this in layout.js for layered popups - function showOverlay() { - $('.dialog-overlay').show(); - } - - function hideOverlay() { - $('.dialog-overlay').hide(); - } - - function audioDriverChanged() { - // ensure any channels removed are restored - var keys = Object.keys(removedVoiceChatChannels); - for (var i=0; i < keys.length; i++) { - $('#voice-inputs-unused').append(removedVoiceChatChannels[keys[i]]); - delete removedVoiceChatChannels[keys[i]]; - } - - context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); - - // refresh dialog - showMusicAudioPanel(true); - } - - function voiceChatChanged() { - // ensure any channels removed are restored - var keys = Object.keys(removedAudioChannels); - for (var i=0; i < keys.length; i++) { - $('#audio-inputs-unused').append(removedAudioChannels[keys[i]]); - delete removedAudioChannels[keys[i]]; - } - - showVoiceChatPanel(true); - } - - function configureDriverSettingsButton() { - if (context.jamClient.TrackHasControlPanel()) { - logger.debug("Showing DRIVER SETTINGS button..."); - $('#btn-driver-settings').show(); - } - else { - logger.debug("Hiding DRIVER SETTINGS button..."); - $('#btn-driver-settings').hide(); - } - } - - function showMusicAudioPanel(refreshLists) { - - setInstructions('audio'); - - $('div[tab-id="music-audio"]').show(); - $('div[tab-id="voice-chat"]').hide(); - - $('#tab-configure-audio').addClass('selected'); - $('#tab-configure-voice').removeClass('selected'); - - if (refreshLists) { - configureDriverSettingsButton(); - - $('#audio-drivers').empty(); - - // determine correct music device to preselect - var deviceId = context.jamClient.TrackGetMusicDeviceID(); - logger.debug("deviceId = " + deviceId); - - // load Audio Driver dropdown - devices = context.jamClient.TrackGetDevices(); - var keys = Object.keys(devices); - - for (var i=0; i < keys.length; i++) { - var template = $('#template-option').html(); - var isSelected = ""; - if (keys[i] === deviceId) { - isSelected = "selected"; - } - var html = context.JK.fillTemplate(template, { - value: keys[i], - label: devices[keys[i]], - selected: isSelected - }); - - $('#audio-drivers').append(html); - } - - $('#audio-inputs-unused').empty(); - $('#track1-input').empty(); - $('#track1-instrument').empty(); - $('#track2-input').empty(); - $('#track2-instrument').empty(); - $('#audio-output-unused').empty(); - $('#audio-output-selection').empty(); - - initDialogData(); - - // TODO: FILTER OUT ANY CHANNELS SELECTED ON THE VOICE CHAT TAB - - // load Unused Inputs - loadOptions($('#audio-inputs-unused'), unusedAudioInputChannels, "device_id", "name", -1); - - // load Track 1 Input(s) - loadOptions($('#track1-input'), track1AudioInputChannels, "device_id", "name", -1); - - // load Track 1 Instrument - var current_instrument = context.jamClient.TrackGetInstrument(1); - loadOptions($('#track1-instrument'), instrument_array, "id", "description", current_instrument); - - // load Track 2 config details if necessary - if (myTrackCount > 1) { - // load Track 2 Input(s) - loadOptions($('#track2-input'), track2AudioInputChannels, "device_id", "name", -1); - - // load Track 2 Instrument - current_instrument = context.jamClient.TrackGetInstrument(2); - loadOptions($('#track2-instrument'), instrument_array, "id", "description", current_instrument); - } - - // load Unused Outputs - loadOptions($('#audio-output-unused'), unusedAudioOutputChannels, "device_id", "name", -1); - - // load Session Audio Output - loadOptions($('#audio-output-selection'), usedAudioOutputChannels, "device_id", "name", -1); - } - } - - function showVoiceChatPanel(refreshLists) { - setInstructions('voice'); - - $('div[tab-id="music-audio"]').hide(); - $('div[tab-id="voice-chat"]').show(); - - $('#tab-configure-audio').removeClass('selected'); - $('#tab-configure-voice').addClass('selected'); - - if (refreshLists) { - $('#voice-inputs-unused').empty(); - $('#voice-inputs-selection').empty(); - - initDialogData(); - - var chatOption = $('#voice-chat-device').val(); - - // populate with unused session inputs - var voiceChatOptions = []; - $.each(unusedAudioInputChannels, function(index, val) { - var deviceId = val.device_id; - if ($('#track1-input > option[value="' + deviceId + '"]').length === 0 && - $('#track2-input > option[value="' + deviceId + '"]').length === 0) { - voiceChatOptions.push(val); - } - }); - - if (chatOption === VOICE_CHAT.SESSION) { - loadOptions($('#voice-inputs-unused'), voiceChatOptions, "device_id", "name", -1); - loadOptions($('#voice-inputs-selection'), usedChatInputChannels, "device_id", "name", -1); - } - - // populate with voice devices - else if (chatOption === VOICE_CHAT.CHAT) { - loadOptions($('#voice-inputs-unused'), unusedChatInputChannels, "device_id", "name", -1); - loadOptions($('#voice-inputs-selection'), usedChatInputChannels, "device_id", "name", -1); - } - - // disable inputs - else if (chatOption === VOICE_CHAT.MIC) { - - } - } - } - - function initDialogData() { - - // clear out arrays - unusedAudioInputChannels = []; - track1AudioInputChannels = []; - track2AudioInputChannels = []; - - unusedAudioOutputChannels = []; - usedAudioOutputChannels = []; - - unusedChatInputChannels = []; - usedChatInputChannels = []; - - // get data needed for listboxes - var channels = context.jamClient.TrackGetChannels(); - - $.each(channels, function(index, val) { - var assignment = context.jamClient.TrackGetAssignment(val.id, val.input); - logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + assignment + - ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat); - - // INPUT - if (context.jamClient.TrackIsMusicDeviceType(val.device_type)) { - if (val.input) { - if (assignment === ASSIGNMENT.CHAT) { - usedChatInputChannels.push(val); - } - else if (assignment === ASSIGNMENT.UNASSIGNED) { - if (!val.chat) { - unusedAudioInputChannels.push(val); - } - else { - unusedChatInputChannels.push(val); - } - } - else if (assignment === ASSIGNMENT.OUTPUT) { - - } - else { - if (assignment === ASSIGNMENT.TRACK1) { - track1AudioInputChannels.push(val); - } - else if (assignment === ASSIGNMENT.TRACK2) { - track2AudioInputChannels.push(val); - } - } - } - - // OUTPUT - else { - if (assignment === ASSIGNMENT.CHAT) { - - } - else if (assignment === ASSIGNMENT.UNASSIGNED) { - if (!val.chat) { - unusedAudioOutputChannels.push(val); - } - } - else if (assignment === ASSIGNMENT.OUTPUT) { - - } - else { - } - } - } - }); - } - - function loadOptions(listbox_id, input_array, id_field, text_field, selected_id) { - $.each(input_array, function(index, val) { - var template = $('#template-option').html(); - var isSelected = ""; - if (val[id_field] === selected_id) { - isSelected = "selected"; - } - var html = context.JK.fillTemplate(template, { - value: val[id_field], - label: val[text_field], - selected: isSelected - }); - - listbox_id.append(html); - }); - } - - function saveSettings() { - if (!validateAudioSettings()) { - return; - } - - if (!validateVoiceChatSettings()) { - return; - } - - saveAudioSettings(); - saveVoiceChatSettings(); - - originalDeviceId = $('#audio-drivers').val(); - $('div[layout-id="configure-audio"]').hide(); - - hideOverlay(); - - // refresh Session screen - sessionModel.refreshCurrentSession(); - } - - function saveAudioSettings() { - - // TRACK 1 INPUTS - $("#track1-input > option").each(function() { - logger.debug("Saving track 1 input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1); - }); - - // TRACK 1 INSTRUMENT - var instrumentVal = $('#track1-instrument').val(); - var instrumentText = $('#track1-instrument > option:selected').text().toLowerCase(); - - logger.debug("Saving track 1 instrument = " + instrumentVal); - context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal); - - // UPDATE SERVER - logger.debug("Updating track " + myTracks[0].trackId + " with instrument " + instrumentText); - var data = {}; - data.instrument_id = instrumentText; - sessionModel.updateTrack(sessionId, myTracks[0].trackId, data); - - if (myTrackCount > 1) { - // TRACK 2 INPUTS - $("#track2-input > option").each(function() { - logger.debug("Saving track 2 input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2); - }); - - // TRACK 2 INSTRUMENT - instrumentVal = $('#track2-instrument').val(); - instrumentText = $('#track2-instrument > option:selected').text().toLowerCase(); - - logger.debug("Saving track 2 instrument = " + instrumentVal); - context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal); - - // UPDATE SERVER - logger.debug("Updating track " + myTracks[1].trackId + " with instrument " + instrumentText); - data.instrument_id = instrumentText; - sessionModel.updateTrack(myTracks[1].trackId, sessionId, data); - } - - // OUTPUT - $("#audio-output-selection > option").each(function() { - logger.debug("Saving session audio output = " + this.value); - context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT); - }); - - context.jamClient.TrackSaveAssignments(); - } - - function saveVoiceChatSettings() { - currentVoiceChat = $('#voice-chat-device').val(); - - logger.debug("Calling TrackSetChatUsesMusic with value = " + currentVoiceChat); - context.jamClient.TrackSetChatUsesMusic(currentVoiceChat); - - $("#voice-inputs-selection > option").each(function() { - logger.debug("Saving chat input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT); - }); - } - - function cancelSettings() { - // reset to original device ID - context.jamClient.TrackSetMusicDevice(originalDeviceId); - - // reset voice chat option to original - $('#voice-chat-device').val(originalVoiceChat); - } - - function validateAudioSettings() { - var isValid = true; - var noTrackErrMsg = 'You must assign at least one input port to each of your tracks. Please update your settings to correct this. If you want to delete a track, please return to the session screen and delete the track by clicking the "x" box in the upper right-hand corner of the track.'; - var noInstrumentErrMsg = 'You must specify what instrument is being played for each track. Please update your settings to correct this.'; - var outputErrMsg = 'You must assign two output ports for stereo session audio to hear music. Please update your settings to correct this.'; - - var errMsg; - - // verify Track 1 Input and Instrument exist - if ($('#track1-input > option').size() === 0 || $('#track1-input > option').size() > 2) { - errMsg = noTrackErrMsg; - isValid = false; - } - - if (isValid) { - if ($('#track1-instrument > option').size() === 0) { - errMsg = noInstrumentErrMsg; - isValid = false; - } - } - - // if Track 2 exists, verify Input and Instrument exist - if (isValid && myTrackCount > 1) { - if ($('#track2-input > option').size() === 0 || $('#track2-input > option').size() > 2) { - errMsg = noTrackErrMsg; - isValid = false; - } - - if (isValid && $('#track2-instrument > option').size() === 0) { - errMsg = noInstrumentErrMsg; - isValid = false; - } - } - - // verify Session Audio Output exists - if (isValid && $('#audio-output-selection > option').size() !== 2) { - errMsg = outputErrMsg; - isValid = false; - } - - if (!isValid) { - showErrorDialog(errMsg); - } - - return isValid; - } - - function validateVoiceChatSettings() { - var isValid = true; - var noTrackErrMsg = 'You must select a voice input.'; - var errMsg; - - currentVoiceChat = $('#voice-chat-device').val(); - if (currentVoiceChat === VOICE_CHAT.SESSION || currentVoiceChat === VOICE_CHAT.CHAT) { - if ($('#voice-inputs-selection > option').size() === 0 || $('#voice-inputs-selection > option').size() > 2) { - errMsg = noTrackErrMsg; - isValid = false; - } - } - else if (currentVoiceChat === VOICE_CHAT.MIC) { - // NO VALIDATION NEEDED - } - - if (!isValid) { - showErrorDialog(errMsg); - } - - return isValid; - } - - function setInstructions(type) { - if (type === 'audio') { - var os = context.jamClient.GetOSAsString(); - $('#instructions', 'div[layout-id="configure-audio"]').html(configure_audio_instructions[os]); - } - else if (type === 'voice') { - $('#instructions', 'div[layout-id="configure-audio"]').html(configure_voice_instructions); - } - } - - function showErrorDialog(msg) { - app.layout.showDialog('error-dialog'); - $('#error-msg', 'div[layout-id="error-dialog"]').html(msg); } this.initialize = function() { diff --git a/app/assets/javascripts/sessionModel.js b/app/assets/javascripts/sessionModel.js index bba12405c..7c6b299ba 100644 --- a/app/assets/javascripts/sessionModel.js +++ b/app/assets/javascripts/sessionModel.js @@ -210,6 +210,23 @@ return foundParticipant; } + function addTrack(sessionId, data) { + logger.debug("track data = " + JSON.stringify(data)); + var url = "/api/sessions/" + sessionId + "/tracks"; + $.ajax({ + type: "POST", + dataType: "json", + contentType: 'application/json', + url: url, + data: JSON.stringify(data), + processData:false, + success: function(response) { + logger.debug("Successfully added track (" + JSON.stringify(data) + ")"); + }, + error: ajaxError + }); + } + function updateTrack(sessionId, trackId, data) { var url = "/api/sessions/" + sessionId + "/tracks/" + trackId; $.ajax({ @@ -226,6 +243,24 @@ }); } + function deleteTrack(trackId) { + if (trackId) { + $.ajax({ + type: "DELETE", + url: "/api/sessions/" + sessionId + "/tracks/" + trackId, + success: function(response) { + // TODO: if in recording, more cleanup to do??? + + // refresh Session screen + refreshCurrentSession(); + }, + error: function(jqXHR, textStatus, errorThrown) { + logger.error("Error deleting track " + trackId); + } + }); + } + } + /** * Make the server calls to join the current user to * the session provided. @@ -297,7 +332,9 @@ this.refreshCurrentSession = refreshCurrentSession; this.subscribe = subscribe; this.participantForClientId = participantForClientId; + this.addTrack = addTrack; this.updateTrack = updateTrack; + this.deleteTrack = deleteTrack; }; })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/utils.js b/app/assets/javascripts/utils.js index 03802aecc..8c5f74160 100644 --- a/app/assets/javascripts/utils.js +++ b/app/assets/javascripts/utils.js @@ -6,6 +6,7 @@ "use strict"; context.JK = context.JK || {}; + var logger = context.JK.logger; var instrumentIconMap24 = { "acoustic guitar": '../assets/content/icon_instrument_guitar24.png', @@ -40,15 +41,15 @@ context.JK.resolveAvatarUrl = function(photo_url) { return photo_url ? photo_url : "/assets/shared/avatar_default.jpg"; - } + }; context.JK.getInstrumentIconMap24 = function() { return instrumentIconMap24; - } + }; context.JK.getInstrumentIconMap45 = function() { return instrumentIconMap45; - } + }; context.JK.getInstrumentIcon24 = function(instrument) { if (instrument in instrumentIconMap24) { @@ -56,7 +57,7 @@ } return instrumentIconMap24["default"]; - } + }; context.JK.getInstrumentIcon45 = function(instrument) { if (instrument in instrumentIconMap45) { @@ -64,19 +65,45 @@ } return instrumentIconMap45["default"]; - } + }; context.JK.getInstruments = function(app, callback) { var url = "/api/instruments"; - var instruments; $.ajax({ type: "GET", + dataType: "json", url: url, success: function(response) { callback(response); }, error: app.ajaxError }); + }; + + context.JK.showErrorDialog = function(app, msg) { + app.layout.showDialog('error-dialog'); + $('#error-msg', 'div[layout-id="error-dialog"]').html(msg); + } + + /* + * 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.search = function(query, app, callback) { @@ -91,7 +118,7 @@ }, error: app.ajaxError }); - } + }; context.JK.sendFriendRequest = function(app, userId, callback) { var url = "/api/users/" + context.JK.currentUserId + "/friend_requests"; @@ -107,7 +134,7 @@ }, error: app.ajaxError }); - } + }; /* * Get the length of a dictionary diff --git a/app/controllers/api_music_sessions_controller.rb b/app/controllers/api_music_sessions_controller.rb index 44b1f5dad..468252132 100644 --- a/app/controllers/api_music_sessions_controller.rb +++ b/app/controllers/api_music_sessions_controller.rb @@ -131,10 +131,13 @@ class ApiMusicSessionsController < ApiController end def track_create + puts "TRACK CONNECTION ID = #{params[:connection_id]}" @track = Track.save(nil, params[:connection_id], params[:instrument_id], params[:sound]) + + puts "TRACK CONNECTION ID = #{@track.connection_id}" respond_with @track, responder: ApiResponder, :status => 201, :location => api_session_track_detail_url(@track.connection.music_session, @track) end diff --git a/app/views/api_music_sessions/show.rabl b/app/views/api_music_sessions/show.rabl index 0f6ce7b57..b9670496e 100644 --- a/app/views/api_music_sessions/show.rabl +++ b/app/views/api_music_sessions/show.rabl @@ -15,7 +15,7 @@ child(:connections => :participants) { end child(:tracks => :tracks) { - attributes :id, :instrument_id, :sound + attributes :id, :connection_id, :instrument_id, :sound } } diff --git a/app/views/clients/_addNewGear.html.erb b/app/views/clients/_addNewGear.html.erb new file mode 100644 index 000000000..bc46a8cce --- /dev/null +++ b/app/views/clients/_addNewGear.html.erb @@ -0,0 +1,16 @@ + +
+
+ <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> +

add new audio gear

+
+
+ To add a new audio device, you must exit your current session and test the device using the JamKazam automated test feature. +

+ +
+
+
\ No newline at end of file diff --git a/app/views/clients/_addTrack.html.erb b/app/views/clients/_addTrack.html.erb new file mode 100644 index 000000000..28eccfd61 --- /dev/null +++ b/app/views/clients/_addTrack.html.erb @@ -0,0 +1,41 @@ + +
+
+ <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> +

add a track

+
+
+ Use arrow buttons to assign audio inputs to this new track, and choose what instrument you are playing on this track. Please note that you may only use one audio device for all audio inputs and outputs. If you don't see an audio device you think should be listed view this help topic to understand why.
+
+
+ Unused Inputs:
+ +

+ ADD NEW AUDIO GEAR +
+
+
+
+ +
+
+ +
+ Track 2 Input:
+ +
+
+ Track 2 Instrument:
+ +
+

+
+ CANCEL  + ADD TRACK +
+
+
+
\ No newline at end of file diff --git a/app/views/clients/_configureTrack.html.erb b/app/views/clients/_configureTrack.html.erb new file mode 100644 index 000000000..949d47654 --- /dev/null +++ b/app/views/clients/_configureTrack.html.erb @@ -0,0 +1,130 @@ + +
+
+ <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> +

configure tracks

+
+
+ + +

+ + +
+ +
+ Audio Driver:
+ +

+ Unused Inputs:
+ +

+ Unused Outputs:
+ +

+ ADD NEW AUDIO GEAR +
+ + + +
+
+




+ +
+
+ +
+
+ DRIVER SETTINGS...


+ Track 1 Input:
+ +

+
+
+ +
+
+ +
+
+ Track 2 Input:
+ +
+

+
+
+
+ +
+
+ +
+
+ Session Audio Output:
+ +
+ + + +
+



+ Track 1 Instrument:
+ +
+
+
+ Track 2 Instrument:
+ +
+
+ +
+ + + +

+ +
+
+
\ No newline at end of file diff --git a/app/views/clients/_error.html.erb b/app/views/clients/_error.html.erb new file mode 100644 index 000000000..a9072ef79 --- /dev/null +++ b/app/views/clients/_error.html.erb @@ -0,0 +1,15 @@ + +
+
+ <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> +

invalid settings

+
+
+ +

+
+ OK +
+
+
+
\ No newline at end of file diff --git a/app/views/clients/_home.html.erb b/app/views/clients/_home.html.erb index 5449d253e..46fc83c5e 100644 --- a/app/views/clients/_home.html.erb +++ b/app/views/clients/_home.html.erb @@ -13,7 +13,7 @@
1 session invitation, 19 public sessions active
+ class="homecard profile">

profile

5 followers, 3 following
diff --git a/app/views/clients/_session.html.erb b/app/views/clients/_session.html.erb index dc7839d35..da6cc36a4 100644 --- a/app/views/clients/_session.html.erb +++ b/app/views/clients/_session.html.erb @@ -60,7 +60,7 @@

my tracks

- - - - - -
-
- <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> -

configure tracks

-
-
- - -

- - -
- -
- Audio Driver:
- -

- Unused Inputs:
- -

- Unused Outputs:
- -

- ADD NEW AUDIO GEAR -
- - - -
-
-




- -
-
- -
-
- DRIVER SETTINGS...


- Track 1 Input:
- -

-
-
- -
-
- -
-
- Track 2 Input:
- -
-

-
-
-
- -
-
- -
-
- Session Audio Output:
- -
- - - -
-



- Track 1 Instrument:
- -
-
-
- Track 2 Instrument:
- -
-
- -
- - - -

- -
-
-
- - -
-
- <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> -

add a track

-
-
- Use arrow buttons to assign audio inputs to this new track, and choose what instrument you are playing on this track. Please note that you may only use one audio device for all audio inputs and outputs. If you don't see an audio device you think should be listed view this help topic to understand why.
-
-
- Unused Inputs:
- -

- ADD NEW AUDIO GEAR -
-
-
-
- <%= image_tag "content/arrow_right_24.png", {:width => 24, :height => 24} %> -
-
- <%= image_tag "content/arrow_left_24.png", {:width => 24, :height => 24} %> -
- Track 2 Input:
- -
-
- Track 2 Instrument:
- -
-

-
- CANCEL  - ADD TRACK -
-
-
-
- -
-
- <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> -

add new audio gear

-
-
- To add a new audio device, you must exit your current session and test the device using the JamKazam automated test feature. -

- -
-
-
- -
-
- <%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %> -

invalid settings

-
-
- -

-
- OK -
-
-
-
+ +<%= render "configureTrack" %> +<%= render "addTrack" %> +<%= render "addNewGear" %> +<%= render "error" %> @@ -363,7 +151,7 @@ {right-vu}
{name}
-
+
<%= image_tag "content/icon_closetrack.png", {:width => 12, :height => 12} %>
@@ -435,5 +223,4 @@ - - + \ No newline at end of file