diff --git a/build/nsis/Mixxx.nsi b/build/nsis/Mixxx.nsi
index 98eece8ef378..a7ab6f2792e3 100644
--- a/build/nsis/Mixxx.nsi
+++ b/build/nsis/Mixxx.nsi
@@ -450,9 +450,11 @@ Section "Uninstall"
Delete "$INSTDIR\controllers\Korg nanoPAD2.midi.xml"
Delete "$INSTDIR\controllers\Korg-nanoKONTROL-2-scripts.js"
Delete "$INSTDIR\controllers\Korg-nanoPAD2-scripts.js"
- Delete "$INSTDIR\controllers\M-Audio-Xponent-scripts.js"
- Delete "$INSTDIR\controllers\M-Audio_Xponent.midi.xml"
+ Delete "$INSTDIR\controllers\korg_nanokontrol2.mixco.output.js"
+ Delete "$INSTDIR\controllers\korg_nanokontrol2.mixco.output.midi.xml"
Delete "$INSTDIR\controllers\M-Audio_Xsession_pro.midi.xml"
+ Delete "$INSTDIR\controllers\maudio_xponent.mixco.output.js"
+ Delete "$INSTDIR\controllers\maudio_xponent.mixco.output.midi.xml"
Delete "$INSTDIR\controllers\Midi-Keyboard.midi.xml"
Delete "$INSTDIR\controllers\Midi_for_light.midi.xml"
Delete "$INSTDIR\controllers\Midi_for_light-scripts.js"
@@ -473,6 +475,8 @@ Section "Uninstall"
Delete "$INSTDIR\controllers\Novation-Launchpad-Mini-scripts.js"
Delete "$INSTDIR\controllers\Novation-Launchpad-Mini.midi.xml"
Delete "$INSTDIR\controllers\Novation-Launchpad-scripts.js"
+ Delete "$INSTDIR\controllers\novation_twitch.mixco.output.js"
+ Delete "$INSTDIR\controllers\novation_twitch.mixco.output.midi.xml"
Delete "$INSTDIR\controllers\Numark DJ2Go.midi.xml"
Delete "$INSTDIR\controllers\Numark Mixtrack Pro.midi.xml"
Delete "$INSTDIR\controllers\Numark MIXTRACK.midi.xml"
diff --git a/res/controllers/M-Audio-Xponent-scripts.js b/res/controllers/M-Audio-Xponent-scripts.js
deleted file mode 100644
index 47236f28ff91..000000000000
--- a/res/controllers/M-Audio-Xponent-scripts.js
+++ /dev/null
@@ -1,519 +0,0 @@
-function MaudioXponent () {}
-
-// ---------- Global variables ----------
-
-MaudioXponent.id = ""; // The ID for the particular device being controlled for use in debugging, set at init time
-MaudioXponent.off = 0x80;
-MaudioXponent.on = 0x90;
-MaudioXponent.mastermeter = 0; //1 for master meter, 0 for channel meter
-MaudioXponent.flashprogress = 8; //flash duration on progress meters
-MaudioXponent.leds = {
- "play": 0x24,
- "cue": 0x23,
- "back": 0x21,
- "fwd": 0x22,
- "in": 0x29,
- "out": 0x2B,
- "loop": 0x2A,
- "loop1": 0x25,
- "loop2": 0x26,
- "loop4": 0x27,
- "loop8": 0x28,
- "leftkey": 0x1C,
- "rightkey": 0x1D,
- "key": 0x1E,
- "pluskey": 0x1F,
- "minkey": 0x20,
- "cue1": 0x17,
- "cue2": 0x18,
- "cue3": 0x19,
- "cue4": 0x1A,
- "cue5": 0x1B,
- "fx1": 0x0C,
- "fx2": 0x0D,
- "fx3": 0x0E,
- "fx4": 0x0F,
- "leftp": 0x10,
- "rightp": 0x11,
- "bigx": 0x12,
- "big-": 0x13,
- "head": 0x14,
- "scratch": 0x15,
- "fadarbutton": 0x07,
- "sync": 0x02,
- "low": 0x08,
- "middle": 0x09,
- "hight": 0x0A,
- "gain": 0x0B,
- "shift": 0x2C
-};
-MaudioXponent.binleds = {
- 8: "filterLowKill",
- 9: "filterMidKill",
- 10: "filterHighKill",
- 18: "keylock",
- 19: "reverse",
- 20: "pfl",
- 33: "back",
- 34: "fwd",
- 36: "play"
-};
-MaudioXponent.hotcues = {
- 23: 1,
- 24: 2,
- 25: 3,
- 26: 4,
- 27: 5
-};
-MaudioXponent.timer = [-1, -1]; // Temporary storage of timer IDs
-MaudioXponent.state = {
- "flashes" : 0,
- "faderpos" : 0,
- "shift1" : 0,
- "shift2" : 0,
- "scrmode1" : 0,
- "scrmode2" : 0,
- "plnumberpos" : 0,
- "plnumberneg" : 0,
- "scratching1" : 0,
- "scratching2" : 0,
-}; // Temporary state variables
-
-// ---------- Functions ----------
-
-MaudioXponent.init = function (id) { // called when the MIDI device is opened & set up
-
- //This code light on all leds and then light off
- midi.sendShortMsg(0xB3,0x14,0x00);
- midi.sendShortMsg(0xB3,0x15,0x00);
- for (var led in MaudioXponent.leds) {
- midi.sendShortMsg(MaudioXponent.on,MaudioXponent.leds[led],0x01);
- midi.sendShortMsg(MaudioXponent.on + 1,MaudioXponent.leds[led],0x01);
- MaudioXponent.pauseScript(15);
- }
- midi.sendShortMsg(0xB3,0x12,0x7F);
- midi.sendShortMsg(0xB3,0x13,0x7F);
- midi.sendShortMsg(0xB3,0x14,0x7F);
- midi.sendShortMsg(0xB3,0x15,0x7F);
- MaudioXponent.pauseScript(500);
- for (var led in MaudioXponent.leds) {
- midi.sendShortMsg(MaudioXponent.on,MaudioXponent.leds[led],0x00);
- midi.sendShortMsg(MaudioXponent.on + 1,MaudioXponent.leds[led],0x00);
- MaudioXponent.pauseScript(15);
- }
- midi.sendShortMsg(0xB3,0x14,0x00);
- midi.sendShortMsg(0xB3,0x15,0x00);
- //end of light on all leds
-
- MaudioXponent.flashdur1 = 0;
- MaudioXponent.flashdur2 = 0;
- engine.connectControl("[Channel1]","visual_playposition","MaudioXponent.playPositionMeter1");
- engine.connectControl("[Channel2]","visual_playposition","MaudioXponent.playPositionMeter2");
- if (MaudioXponent.mastermeter == 1) {
- engine.connectControl("[Master]","VuMeterL","MaudioXponent.volumeLEDs1");
- engine.connectControl("[Master]","VuMeterR","MaudioXponent.volumeLEDs2");
- } else {
- engine.connectControl("[Channel1]","VuMeter","MaudioXponent.volumeLEDs1");
- engine.connectControl("[Channel2]","VuMeter","MaudioXponent.volumeLEDs2");
- }
-
- engine.connectControl("[Channel1]","hotcue_1_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel1]","hotcue_2_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel1]","hotcue_3_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel1]","hotcue_4_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel1]","hotcue_5_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel2]","hotcue_1_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel2]","hotcue_2_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel2]","hotcue_3_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel2]","hotcue_4_enabled","MaudioXponent.hotcue");
- engine.connectControl("[Channel2]","hotcue_5_enabled","MaudioXponent.hotcue");
-
- engine.connectControl("[Channel1]", "loop_enabled", "MaudioXponent.onLoopExit");
- engine.connectControl("[Channel1]", "loop_start_position", "MaudioXponent.onLoopIn");
- engine.connectControl("[Channel1]", "loop_end_position", "MaudioXponent.onLoopOut");
- engine.connectControl("[Channel2]", "loop_enabled", "MaudioXponent.onLoopExit");
- engine.connectControl("[Channel2]", "loop_start_position", "MaudioXponent.onLoopIn");
- engine.connectControl("[Channel2]", "loop_end_position", "MaudioXponent.onLoopOut");
-
- //engine.connectControl("[Channel1]","bpm","MaudioXponent.bpmsync");
-
-};
-
-MaudioXponent.wheel = function (channel, control, value, status) {
- var currentdeck = channel+1;
-
- // In either case, register the movement
-
- if (MaudioXponent.state["shift"+currentdeck] == 1) {
- if (value > 64) {
- MaudioXponent.state["plnumberpos"]++;
- if (MaudioXponent.state["plnumberpos"] % 12 == 0) {
- engine.setValue("[Playlist]","SelectTrackKnob",1);
- }
- } else if (value < 64) {
- MaudioXponent.state["plnumberneg"]++;
- if (MaudioXponent.state["plnumberneg"] % 12 == 0) {
- engine.setValue("[Playlist]","SelectTrackKnob",-1);
- }
- }
- }else{
- if (MaudioXponent.state["scratching"+currentdeck] == 1) { //scratch mode on
- engine.scratchTick(currentdeck, value-64);
- } else { //normal wheel mode
- engine.setValue("[Channel"+currentdeck+"]", "jog", (value-64)/8);
- }
- }
-};
-
-MaudioXponent.wheelbuton = function(channel, control, value, status) {
- var currentdeck = channel+1;
- if (MaudioXponent.state["scrmode"+currentdeck] == 1) { //scratch mode on
- engine.scratchEnable(currentdeck, 3*128, 33+1/3, 1.0/8, (1.0/8)/32);
- MaudioXponent.state["scratching"+currentdeck] = true;
- }
-};
-
-MaudioXponent.wheelbutoff = function(channel, control, value, status) {
- var currentdeck = channel+1;
- engine.scratchDisable (currentdeck);
- MaudioXponent.state["scratching"+currentdeck] = false;
-};
-
-MaudioXponent.pauseScript = function(ms) {
- startDate = new Date();
- currentDate = null;
- while(currentDate-startDate < ms) currentDate = new Date();
-};
-
-MaudioXponent.playPositionMeter1 = function(value) {
- if (value >= 0.75) {
- MaudioXponent.flashdur1++;;
- if (MaudioXponent.flashdur1 == MaudioXponent.flashprogress) {
- midi.sendShortMsg(0xB3,0x14,0x00);
- }
- if (MaudioXponent.flashdur1 >= MaudioXponent.flashprogress*2) {
- midi.sendShortMsg(0xB3,0x14,MaudioXponent.convert(value));
- MaudioXponent.flashdur1 = 0;
- }
- }else{
- midi.sendShortMsg(0xB3,0x14,MaudioXponent.convert(value));
- }
-};
-
-MaudioXponent.playPositionMeter2 = function(value) {
- if (value >= 0.75) {
- MaudioXponent.flashdur2++;;
- if (MaudioXponent.flashdur2 == MaudioXponent.flashprogress) {
- midi.sendShortMsg(0xB3,0x15,0x00);
- }
- if (MaudioXponent.flashdur2 >= MaudioXponent.flashprogress*2) {
- midi.sendShortMsg(0xB3,0x15,MaudioXponent.convert(value));
- MaudioXponent.flashdur2 = 0;
- }
- }else{
- midi.sendShortMsg(0xB3,0x15,MaudioXponent.convert(value));
- }
-};
-
-MaudioXponent.volumeLEDs1 = function(value) {
- midi.sendShortMsg(0xB3,0x12,MaudioXponent.convert(value));
-};
-
-MaudioXponent.volumeLEDs2 = function(value) {
- midi.sendShortMsg(0xB3,0x13,MaudioXponent.convert(value));
-};
-
-MaudioXponent.convert = function(value) {
- value = value*127;
- value = value.toFixed(0);
- value = value.toString(16);
- return (value);
-};
-
-MaudioXponent.actbin = function(channel, control, value, status) { // Generic binary button
- script.debug(channel, control, value, status);
- var currentdeck = channel+1;
- var activenow = engine.getValue("[Channel"+currentdeck+"]", MaudioXponent.binleds[control]);
- if (activenow) { // If currently active
- engine.setValue("[Channel"+currentdeck+"]",MaudioXponent.binleds[control], 0); // Stop
- midi.sendShortMsg(MaudioXponent.off + channel,control, 0x00); // Turn off the LED
- }else { // If not currently active
- engine.setValue("[Channel"+currentdeck+"]",MaudioXponent.binleds[control], 1); // Start
- midi.sendShortMsg(MaudioXponent.on + channel,control, 0x01); // Turn on the LED
- }
-};
-
-MaudioXponent.actbinstop = function(channel, control, value, status) { // Generic binary button
- script.debug(channel, control, value, status);
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]",MaudioXponent.binleds[control],0); // Stop
- midi.sendShortMsg(MaudioXponent.off + channel,control,0x00); // Turn off the LED
-};
-
-MaudioXponent.hotcue = function(channel, control, value, status) { // Generic binary button
- var channelnow = 0;
- if (control == "[Channel2]") {
- channelnow = 1;
- }
- switch (value) {
- case "hotcue_1_enabled":
- if (channel == 1){
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x17,0x01); // Turn on the LED
- }else{
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x17,0x00); // Turn off the LED
- }
- break;
- case "hotcue_2_enabled":
- if (channel == 1){
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x18,0x01); // Turn on the LED
- }else{
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x18,0x00); // Turn off the LED
- }
- break;
- case "hotcue_3_enabled":
- if (channel == 1){
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x19,0x01); // Turn on the LED
- }else{
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x19,0x00); // Turn off the LED
- }
- break;
- case "hotcue_4_enabled":
- if (channel == 1){
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x1A,0x01); // Turn on the LED
- }else{
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x1A,0x00); // Turn off the LED
- }
- break;
- case "hotcue_5_enabled":
- if (channel == 1){
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x1B,0x01); // Turn on the LED
- }else{
- midi.sendShortMsg(MaudioXponent.on + channelnow,0x1B,0x00); // Turn off the LED
- }
- break;
- }
-};
-
-MaudioXponent.hotcueset = function(channel, control, value, status) {
- //MaudioXponent.debug(channel, control, value, status)
- var currentdeck = channel+1;
- if (MaudioXponent.state["shift"+currentdeck] == 1) {
- engine.setValue("[Channel"+currentdeck+"]","hotcue_"+MaudioXponent.hotcues[control]+"_clear",1);
- }else{
- engine.setValue("[Channel"+currentdeck+"]","hotcue_"+MaudioXponent.hotcues[control]+"_activate",1);
- }
-};
-
-MaudioXponent.onLoopIn = function(channel, control, value, status)
-{
- channelnow = control == "[Channel2]" ? 1 : 0;
- midi.sendShortMsg(MaudioXponent.on + channelnow, 0x29,
- engine.getValue (control, value) != -1);
- /* TODO.
- if (-1 == engine.getValue(control, "loop_end_position"))
- {
- MaudioXponent.state["flashes"] = 0; // initialize number of flashes
- MaudioXponent.timer[channelnow] = engine.beginTimer(
- 250, "MaudioXponent.flashled("+ channelnow +",\"0x2B\")");
- }
- */
-}
-
-MaudioXponent.onLoopOut = function(channel, control, value, status)
-{
- channelnow = control == "[Channel2]" ? 1 : 0;
- /*
- if (MaudioXponent.timer[channelnow] != -1) {
- engine.stopTimer (MaudioXponent.timer[channelnow]);
- MaudioXponent.timer[channelnow] = -1;
- }
- */
- midi.sendShortMsg(MaudioXponent.on + channelnow, 0x2B,
- engine.getValue (control, value) != -1);
-}
-
-MaudioXponent.onLoopExit = function(channel, control, value, status)
-{
- channelnow = control == "[Channel2]" ? 1 : 0;
- midi.sendShortMsg(MaudioXponent.on + channelnow, 0x2A,
- engine.getValue (control, value) == 1);
-}
-
-MaudioXponent.loopin = function(channel, control, value, status) {
- //MaudioXponent.debug(channel, control, value, status)
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","loop_in", 1);
-};
-
-MaudioXponent.loopout = function(channel, control, value, status) {
- //MaudioXponent.debug(channel, control, value, status)
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]", "loop_out", 1);
-};
-
-MaudioXponent.loopexit = function(channel, control, value, status) {
- var currentdeck = channel+1;
- var activenow = engine.getValue("[Channel"+currentdeck+"]", "reloop_exit");
- engine.setValue("[Channel"+currentdeck+"]", "reloop_exit", 1);
-};
-
-MaudioXponent.flashled = function (channel, control) {
- MaudioXponent.state["flashes"]++;
- if (MaudioXponent.state["flashes"] % 2 == 0) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- }else {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x00); // Turn off the LED
- }
-};
-
-MaudioXponent.faderbuttonon = function(channel, control, value, status) {
- //script.debug(channel, control, value, status);
- MaudioXponent.state["faderpos"] = engine.getValue("[Master]","crossfader");
- if (MaudioXponent.state["faderpos"] <= -0.90 && channel == 1) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Master]","crossfader",0);
- }else if (MaudioXponent.state["faderpos"] >= 0.90 && channel == 0) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Master]","crossfader",0);
- }
-};
-
-MaudioXponent.faderbuttonoff = function(channel, control, value, status) {
- //script.debug(channel, control, value, status);
- if (MaudioXponent.state["faderpos"] <= -0.90 && channel == 1) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x00); // Turn off the LED
- engine.setValue("[Master]","crossfader",MaudioXponent.state["faderpos"]);
- }else if (MaudioXponent.state["faderpos"] >= 0.90 && channel == 0) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x00); // Turn off the LED
- engine.setValue("[Master]","crossfader",MaudioXponent.state["faderpos"]);
- }
-};
-
-MaudioXponent.bpmsync = function(channel, control, value) {
- print (channel);
- print (control);
-};
-
-MaudioXponent.pitch = function(channel, control, value, status) {
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","rate",script.pitch(control, value, status));
-};
-
-MaudioXponent.secondaryon = function(channel, control, value, status) {
- var currentdeck = channel+1;
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- MaudioXponent.state["shift"+currentdeck] = 1;
-};
-
-MaudioXponent.secondaryoff = function(channel, control, value, status) {
- var currentdeck = channel+1;
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x00); // Turn on the LED
- MaudioXponent.state["shift"+currentdeck] = 0;
-};
-
-MaudioXponent.flanger = function(channel, control, value, status) {
- //script.debug(channel, control, value, status);
- if (control == 12) {
- var activenow = engine.getValue("[Channel1]","flanger");
- if (activenow == 1) { // If currently active
- midi.sendShortMsg(MaudioXponent.on+1,control,0x00); // Turn off the LED
- engine.setValue("[Channel1]","flanger",0);
- }else{
- midi.sendShortMsg(MaudioXponent.on+1,control,0x01); // Turn on the LED
- engine.setValue("[Channel1]","flanger",1);
- }
- }else if (control == 13) {
- var activenow = engine.getValue("[Channel2]","flanger");
- if (activenow == 1) { // If currently active
- midi.sendShortMsg(MaudioXponent.on+1,control,0x00); // Turn off the LED
- engine.setValue("[Channel2]","flanger",0);
- }else{
- midi.sendShortMsg(MaudioXponent.on+1,control,0x01); // Turn on the LED
- engine.setValue("[Channel2]","flanger",1);
- }
- }
-};
-
-MaudioXponent.scrmode = function(channel, control, value, status) {
- var currentdeck = channel+1;
- if (MaudioXponent.state["scrmode"+currentdeck] == 1) {
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x00); // Turn off the LED
- MaudioXponent.state["scrmode"+currentdeck] = 0;
- }else{
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- MaudioXponent.state["scrmode"+currentdeck] = 1;
- }
-};
-
-MaudioXponent.playlist = function(channel, control, value, status) {
- var currentdeck = channel+1;
- switch (control) {
- case 28:
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Playlist]","SelectPrevTrack",1);
- break;
- case 29:
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Playlist]","SelectNextTrack",1);
- break;
- case 30:
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- var activenow = engine.getValue("[Channel"+currentdeck+"]","play");
- if (activenow == 1) { // If currently active
- engine.setValue("[Playlist]","LoadSelectedIntoFirstStopped",1);
- }else{
- engine.setValue("[Channel"+currentdeck+"]","LoadSelectedTrack",1);
- }
- break;
- case 31:
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Playlist]","SelectPrevPlaylist",1);
- break;
- case 32:
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
- engine.setValue("[Playlist]","SelectNextPlaylist",1);
- break;
- }
-};
-
-MaudioXponent.playlistoff = function(channel, control, value, status) {
- midi.sendShortMsg(MaudioXponent.off + channel,control,0x00); // Turn off the LED
-};
-
-MaudioXponent.cuedefon = function(channel, control, value, status) {
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","cue_default",1);
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
-};
-
-MaudioXponent.cuedefoff = function(channel, control, value, status) {
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","cue_default",0);
- midi.sendShortMsg(MaudioXponent.off + channel,control,0x00); // Turn off the LED
-};
-
-MaudioXponent.volbuttonon = function(channel, control, value, status) {
- //script.debug(channel, control, value, status);
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","volume",0);
- midi.sendShortMsg(MaudioXponent.on + channel,control,0x01); // Turn on the LED
-};
-
-MaudioXponent.volbuttonoff = function(channel, control, value, status) {
- //script.debug(channel, control, value, status);
- var currentdeck = channel+1;
- engine.setValue("[Channel"+currentdeck+"]","volume",1);
- midi.sendShortMsg(MaudioXponent.off + channel,control,0x00); // Turn off the LED
-};
-
-MaudioXponent.shutdown = function (id) { // called when the MIDI device is closed
-
- for (var led in MaudioXponent.leds) {
- midi.sendShortMsg(MaudioXponent.on,MaudioXponent.leds[led],0x00); // Turn off deck 1 lights
- midi.sendShortMsg(MaudioXponent.on + 1,MaudioXponent.leds[led],0x00); // Turn off deck 2 lights
- }
- midi.sendShortMsg(0xB3,0x14,0x00);
- midi.sendShortMsg(0xB3,0x15,0x00);
-
-};
-
diff --git a/res/controllers/M-Audio_Xponent.midi.xml b/res/controllers/M-Audio_Xponent.midi.xml
deleted file mode 100644
index 9c7d4f5f2d67..000000000000
--- a/res/controllers/M-Audio_Xponent.midi.xml
+++ /dev/null
@@ -1,1045 +0,0 @@
-
-
-
- M-Audio Xponent
- Luca Franceschini, Juan Pedro Bolívar Puente
- Make sure to set the bank switch on the bottom of the Xponent to A.
-
-
-
-
-
-
-
-
-
- [Master]
- crossfader
- 0xB2
- 7
- fader
-
-
- [Master]
- headMix
- 0xB2
- 13
- fader
-
-
- [Channel1]
- MaudioXponent.faderbuttonon
- 0x90
- 7
-
-
-
-
-
- [Channel1]
- MaudioXponent.faderbuttonoff
- 0x80
- 7
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 36
-
-
-
-
-
- [Channel1]
- play
- 0x80
- 36
- button
-
-
- [Channel1]
- MaudioXponent.cuedefon
- 0x90
- 35
-
-
-
-
-
- [Channel1]
- MaudioXponent.cuedefoff
- 0x80
- 35
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 33
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbinstop
- 0x80
- 33
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 34
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbinstop
- 0x80
- 34
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 19
-
-
-
-
-
- [Channel1]
- volume
- 0xB0
- 7
- fader
-
-
- [Channel1]
- MaudioXponent.pitch
- 0xE0
- 0
-
-
-
-
-
- [Channel1]
- MaudioXponent.wheel
- 0xB0
- 22
-
-
-
-
-
- [Channel1]
- MaudioXponent.wheelbuton
- 0x90
- 22
-
-
-
-
-
- [Channel1]
- MaudioXponent.wheelbutoff
- 0x80
- 22
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 20
-
-
-
-
-
- [Channel1]
- pregain
- 0xB0
- 11
- fader
-
-
- [Channel1]
- filterLow
- 0xB0
- 8
- fader
-
-
- [Channel1]
- filterMid
- 0xB0
- 9
- fader
-
-
- [Channel1]
- filterHigh
- 0xB0
- 10
- fader
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 8
-
-
-
-
-
- [Channel1]
- filterLowKill
- 0x80
- 8
- button
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 9
-
-
-
-
-
- [Channel1]
- filterMidKill
- 0x80
- 9
- button
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 10
-
-
-
-
-
- [Channel1]
- filterHighKill
- 0x80
- 10
- button
-
-
- [Channel1]
- rate_temp_up
- 0x90
- 16
- button
-
-
- [Channel1]
- rate_temp_up
- 0x80
- 16
- button
-
-
- [Channel1]
- rate_temp_down
- 0x90
- 17
- button
-
-
- [Channel1]
- rate_temp_down
- 0x80
- 17
- button
-
-
- [Channel1]
- beatsync
- 0x90
- 2
- button
-
-
- [Channel1]
- beatsync
- 0x80
- 2
- button
-
-
- [Channel1]
- MaudioXponent.loopin
- 0x90
- 41
-
-
-
-
-
- [Channel1]
- MaudioXponent.loopexit
- 0x90
- 42
-
-
-
-
-
- [Channel1]
- MaudioXponent.loopout
- 0x90
- 43
-
-
-
-
-
- [Channel1]
- MaudioXponent.hotcueset
- 0x90
- 23
-
-
-
-
-
- [Channel1]
- MaudioXponent.hotcueset
- 0x90
- 24
-
-
-
-
-
- [Channel1]
- MaudioXponent.hotcueset
- 0x90
- 25
-
-
-
-
-
- [Channel1]
- MaudioXponent.hotcueset
- 0x90
- 26
-
-
-
-
-
- [Channel1]
- MaudioXponent.hotcueset
- 0x90
- 27
-
-
-
-
-
- [Channel1]
- MaudioXponent.secondaryon
- 0x90
- 44
-
-
-
-
-
- [Channel1]
- MaudioXponent.secondaryoff
- 0x80
- 44
-
-
-
-
-
- [Channel1]
- MaudioXponent.scrmode
- 0x90
- 21
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlist
- 0x90
- 28
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlistoff
- 0x80
- 28
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlist
- 0x90
- 29
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlistoff
- 0x80
- 29
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlist
- 0x90
- 30
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlistoff
- 0x80
- 30
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlist
- 0x90
- 31
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlistoff
- 0x80
- 31
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlist
- 0x90
- 32
-
-
-
-
-
- [Channel1]
- MaudioXponent.playlistoff
- 0x80
- 32
-
-
-
-
-
- [Channel1]
- MaudioXponent.volbuttonon
- 0x90
- 11
-
-
-
-
-
- [Channel1]
- MaudioXponent.volbuttonoff
- 0x80
- 11
-
-
-
-
-
- [Channel2]
- MaudioXponent.faderbuttonon
- 0x91
- 7
-
-
-
-
-
- [Channel2]
- MaudioXponent.faderbuttonoff
- 0x81
- 7
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 36
-
-
-
-
-
- [Channel2]
- play
- 0x81
- 36
- button
-
-
- [Channel2]
- MaudioXponent.cuedefon
- 0x91
- 35
-
-
-
-
-
- [Channel2]
- MaudioXponent.cuedefoff
- 0x81
- 35
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 33
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbinstop
- 0x81
- 33
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 34
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbinstop
- 0x81
- 34
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 19
-
-
-
-
-
- [Channel2]
- volume
- 0xB1
- 7
- fader
-
-
- [Channel2]
- MaudioXponent.pitch
- 0xE1
- 0
-
-
-
-
-
- [Channel2]
- MaudioXponent.wheel
- 0xB1
- 22
-
-
-
-
-
- [Channel2]
- MaudioXponent.wheelbuton
- 0x91
- 22
-
-
-
-
-
- [Channel2]
- MaudioXponent.wheelbutoff
- 0x81
- 22
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 20
-
-
-
-
-
- [Channel2]
- pregain
- 0xB1
- 11
- fader
-
-
- [Channel2]
- filterLow
- 0xB1
- 8
- fader
-
-
- [Channel2]
- filterMid
- 0xB1
- 9
- fader
-
-
- [Channel2]
- filterHigh
- 0xB1
- 10
- fader
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 8
-
-
-
-
-
- [Channel2]
- filterLowKill
- 0x81
- 8
- button
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 9
-
-
-
-
-
- [Channel2]
- filterMidKill
- 0x81
- 9
- button
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 10
-
-
-
-
-
- [Channel2]
- filterHighKill
- 0x81
- 10
- button
-
-
- [Channel2]
- rate_temp_up
- 0x91
- 16
- button
-
-
- [Channel2]
- rate_temp_up
- 0x81
- 16
- button
-
-
- [Channel2]
- rate_temp_down
- 0x91
- 17
- button
-
-
- [Channel2]
- rate_temp_down
- 0x81
- 17
- button
-
-
- [Channel2]
- beatsync
- 0x91
- 2
- button
-
-
- [Channel2]
- beatsync
- 0x81
- 2
- button
-
-
- [Channel2]
- MaudioXponent.loopin
- 0x91
- 41
-
-
-
-
-
- [Channel2]
- MaudioXponent.loopexit
- 0x91
- 42
-
-
-
-
-
- [Channel2]
- MaudioXponent.loopout
- 0x91
- 43
-
-
-
-
-
- [Channel2]
- MaudioXponent.hotcueset
- 0x91
- 23
-
-
-
-
-
- [Channel2]
- MaudioXponent.hotcueset
- 0x91
- 24
-
-
-
-
-
- [Channel2]
- MaudioXponent.hotcueset
- 0x91
- 25
-
-
-
-
-
- [Channel2]
- MaudioXponent.hotcueset
- 0x91
- 26
-
-
-
-
-
- [Channel2]
- MaudioXponent.hotcueset
- 0x91
- 27
-
-
-
-
-
- [Channel2]
- MaudioXponent.secondaryon
- 0x91
- 44
-
-
-
-
-
- [Channel2]
- MaudioXponent.secondaryoff
- 0x81
- 44
-
-
-
-
-
- [Channel2]
- MaudioXponent.flanger
- 0x91
- 12
-
-
-
-
-
- [Channel2]
- MaudioXponent.flanger
- 0x91
- 13
-
-
-
-
-
- [Flanger]
- lfoDepth
- 0xB1
- 12
- fader
-
-
- [Flanger]
- lfoDelay
- 0xB1
- 13
- fader
-
-
- [Flanger]
- lfoPeriod
- 0xB1
- 14
- fader
-
-
- [Channel2]
- MaudioXponent.scrmode
- 0x91
- 21
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlist
- 0x91
- 28
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlistoff
- 0x81
- 28
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlist
- 0x91
- 29
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlistoff
- 0x81
- 29
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlist
- 0x91
- 30
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlistoff
- 0x81
- 30
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlist
- 0x91
- 31
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlistoff
- 0x81
- 31
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlist
- 0x91
- 32
-
-
-
-
-
- [Channel2]
- MaudioXponent.playlistoff
- 0x81
- 32
-
-
-
-
-
- [Channel2]
- MaudioXponent.volbuttonon
- 0x91
- 11
-
-
-
-
-
- [Channel2]
- MaudioXponent.volbuttonoff
- 0x81
- 11
-
-
-
-
-
- [Channel1]
- MaudioXponent.actbin
- 0x90
- 18
-
-
-
-
-
- [Channel2]
- MaudioXponent.actbin
- 0x91
- 18
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/controllers/korg_nanokontrol2.mixco.output.js b/res/controllers/korg_nanokontrol2.mixco.output.js
new file mode 100644
index 000000000000..40372c2c7cbe
--- /dev/null
+++ b/res/controllers/korg_nanokontrol2.mixco.output.js
@@ -0,0 +1,8214 @@
+/*
+ * File generated with Mixco framework version: 2.0.2
+ * More info at:
+ */
+
+MIXCO_SCRIPT_FILENAME = '/home/raskolnikov/dev/mixco/script/korg_nanokontrol2.mixco.litcoffee';
+
+require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+ })();
+
+ exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+ };
+
+ exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+ })(value.Value);
+
+ exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+ })(exports.Behaviour);
+
+ exports.call = factory(exports.Call);
+
+ exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+ })(exports.Behaviour);
+
+ exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+ })(exports.Output);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+ };
+
+ exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+ };
+
+ exports.switch_ = exports["switch"];
+
+ exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+ })(exports.Behaviour);
+
+ exports.mapIn = factory(exports.MapIn);
+
+ exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+ })(exports.Output);
+
+ exports.mapOut = factory(exports.MapOut);
+
+ exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+ })(multi(exports.MapIn, exports.MapOut));
+
+ exports.map = factory(exports.Map);
+
+ exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+ };
+
+ exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+ };
+
+ exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+ };
+
+ exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+ };
+
+ exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+ })(exports.Output);
+
+ exports.chooser = factory(exports.Chooser);
+
+ exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+ })(exports.Behaviour);
+
+ exports.when = factory(exports.When);
+
+ exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+ })(exports.Output);
+
+ exports.action = factory(exports.Action);
+
+ exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+ };
+
+ exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+ };
+
+ exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+ };
+
+ exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+ };
+
+ exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+ };
+
+ exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+ };
+
+}).call(this);
+
+},{"./transform":7,"./util":8,"./value":9,"events":10,"heterarchy":13,"underscore":16}],4:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var assert, exports, konsole;
+
+ assert = require('./util').assert;
+
+ konsole = this;
+
+ exports = konsole;
+
+ if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+ }
+
+ if (konsole.info == null) {
+ konsole.info = konsole.log;
+ }
+
+ if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+ }
+
+ if (konsole.error == null) {
+ konsole.error = konsole.log;
+ }
+
+ if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+ }
+
+ if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+ }
+
+ if (konsole.assert == null) {
+ konsole.assert = assert;
+ }
+
+}).call(this);
+
+},{"./util":8}],5:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+ multi = require('heterarchy').multi;
+
+ ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+ behaviour = require('./behaviour');
+
+ ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+ exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+ exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+ exports.MIDI_CC = MIDI_CC = 0xB;
+
+ exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+ midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+ };
+
+ exports.midiId = midiId;
+
+ pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+ };
+
+ noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+ };
+
+ noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+ };
+
+ ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+ };
+
+ exports.pbIds = pbIds;
+
+ exports.noteOnIds = noteOnIds;
+
+ exports.noteIds = noteIds;
+
+ exports.ccIds = ccIds;
+
+ exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+ };
+
+ exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+ })(behaviour.Actor);
+
+ exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+ })(exports.Control);
+
+ exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+ })(exports.Control);
+
+ exports.input = factory(exports.InControl);
+
+ exports.output = factory(exports.OutControl);
+
+ exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+ })(multi(exports.InControl, exports.OutControl));
+
+ exports.control = factory(exports.InOutControl);
+
+}).call(this);
+
+},{"./behaviour":3,"./util":8,"heterarchy":13,"underscore":16}],6:[function(require,module,exports){
+(function (process){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+ Control = require('./control').Control;
+
+ ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+ require('./console');
+
+ basename = require('path').basename;
+
+ S = require('string');
+
+ _ = require('underscore');
+
+ exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+ };
+
+ exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+ };
+
+ exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+ };
+
+ exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+ })();
+
+}).call(this);
+
+}).call(this,require('_process'))
+},{"./console":4,"./control":5,"./util":8,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],7:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+ exports.identity = function(v) {
+ return v;
+ };
+
+ exports.identity.inverse = exports.identity;
+
+ exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+ };
+
+ exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+ };
+
+ exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+ };
+
+ exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+ };
+
+ exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+ };
+
+ exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.identityT = identityT = exports.transformI(exports.identity);
+
+ exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+ exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+ exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+ };
+
+ exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+ };
+
+ exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+ exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+ };
+
+}).call(this);
+
+},{}],8:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+ };
+
+ Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+ };
+
+ Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+ };
+
+ Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+ };
+
+ exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+ };
+
+ exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+ };
+
+ exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+ };
+
+ exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+ };
+
+ exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+ };
+
+ exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+ };
+
+ exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+ };
+
+}).call(this);
+
+},{}],9:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+ events = require('events');
+
+ util = require('./util');
+
+ factory = util.factory;
+
+ exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+ })(events.EventEmitter);
+
+ exports.value = factory(exports.Value);
+
+ exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+ })();
+
+ exports["const"] = factory(exports.Const);
+
+ exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+ })(exports.Value);
+
+ exports.reduce = factory(exports.Reduce);
+
+ exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+ })(exports.Value);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+ };
+
+}).call(this);
+
+},{"./util":8,"events":10}],10:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+function EventEmitter() {
+ this._events = this._events || {};
+ this._maxListeners = this._maxListeners || undefined;
+}
+module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+EventEmitter.EventEmitter = EventEmitter;
+
+EventEmitter.prototype._events = undefined;
+EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!isNumber(n) || n < 0 || isNaN(n))
+ throw TypeError('n must be a positive number');
+ this._maxListeners = n;
+ return this;
+};
+
+EventEmitter.prototype.emit = function(type) {
+ var er, handler, len, args, i, listeners;
+
+ if (!this._events)
+ this._events = {};
+
+ // If there is no 'error' event listener then throw.
+ if (type === 'error') {
+ if (!this._events.error ||
+ (isObject(this._events.error) && !this._events.error.length)) {
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ }
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ }
+
+ handler = this._events[type];
+
+ if (isUndefined(handler))
+ return false;
+
+ if (isFunction(handler)) {
+ switch (arguments.length) {
+ // fast cases
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ // slower
+ default:
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+
+ listeners = handler.slice();
+ len = listeners.length;
+ for (i = 0; i < len; i++)
+ listeners[i].apply(this, args);
+ }
+
+ return true;
+};
+
+EventEmitter.prototype.addListener = function(type, listener) {
+ var m;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events)
+ this._events = {};
+
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (this._events.newListener)
+ this.emit('newListener', type,
+ isFunction(listener.listener) ?
+ listener.listener : listener);
+
+ if (!this._events[type])
+ // Optimize the case of one listener. Don't need the extra array object.
+ this._events[type] = listener;
+ else if (isObject(this._events[type]))
+ // If we've already got an array, just append.
+ this._events[type].push(listener);
+ else
+ // Adding the second element, need to change to array.
+ this._events[type] = [this._events[type], listener];
+
+ // Check for listener leak
+ if (isObject(this._events[type]) && !this._events[type].warned) {
+ var m;
+ if (!isUndefined(this._maxListeners)) {
+ m = this._maxListeners;
+ } else {
+ m = EventEmitter.defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ if (typeof console.trace === 'function') {
+ // not supported in IE 10
+ console.trace();
+ }
+ }
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ var fired = false;
+
+ function g() {
+ this.removeListener(type, g);
+
+ if (!fired) {
+ fired = true;
+ listener.apply(this, arguments);
+ }
+ }
+
+ g.listener = listener;
+ this.on(type, g);
+
+ return this;
+};
+
+// emits a 'removeListener' event iff the listener was removed
+EventEmitter.prototype.removeListener = function(type, listener) {
+ var list, position, length, i;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events || !this._events[type])
+ return this;
+
+ list = this._events[type];
+ length = list.length;
+ position = -1;
+
+ if (list === listener ||
+ (isFunction(list.listener) && list.listener === listener)) {
+ delete this._events[type];
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+
+ } else if (isObject(list)) {
+ for (i = length; i-- > 0;) {
+ if (list[i] === listener ||
+ (list[i].listener && list[i].listener === listener)) {
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (list.length === 1) {
+ list.length = 0;
+ delete this._events[type];
+ } else {
+ list.splice(position, 1);
+ }
+
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ var key, listeners;
+
+ if (!this._events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!this._events.removeListener) {
+ if (arguments.length === 0)
+ this._events = {};
+ else if (this._events[type])
+ delete this._events[type];
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ for (key in this._events) {
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = {};
+ return this;
+ }
+
+ listeners = this._events[type];
+
+ if (isFunction(listeners)) {
+ this.removeListener(type, listeners);
+ } else {
+ // LIFO order
+ while (listeners.length)
+ this.removeListener(type, listeners[listeners.length - 1]);
+ }
+ delete this._events[type];
+
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ var ret;
+ if (!this._events || !this._events[type])
+ ret = [];
+ else if (isFunction(this._events[type]))
+ ret = [this._events[type]];
+ else
+ ret = this._events[type].slice();
+ return ret;
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ var ret;
+ if (!emitter._events || !emitter._events[type])
+ ret = 0;
+ else if (isFunction(emitter._events[type]))
+ ret = 1;
+ else
+ ret = emitter._events[type].length;
+ return ret;
+};
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+
+},{}],11:[function(require,module,exports){
+(function (process){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// resolves . and .. elements in a path array with directory names there
+// must be no slashes, empty elements, or device names (c:\) in the array
+// (so also no leading and trailing slashes - it does not distinguish
+// relative and absolute paths)
+function normalizeArray(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up--; up) {
+ parts.unshift('..');
+ }
+ }
+
+ return parts;
+}
+
+// Split a filename into [root, dir, basename, ext], unix version
+// 'root' is just a slash, or nothing.
+var splitPathRe =
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+var splitPath = function(filename) {
+ return splitPathRe.exec(filename).slice(1);
+};
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+};
+
+// path.normalize(path)
+// posix version
+exports.normalize = function(path) {
+ var isAbsolute = exports.isAbsolute(path),
+ trailingSlash = substr(path, -1) === '/';
+
+ // Normalize the path
+ path = normalizeArray(filter(path.split('/'), function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+
+ return (isAbsolute ? '/' : '') + path;
+};
+
+// posix version
+exports.isAbsolute = function(path) {
+ return path.charAt(0) === '/';
+};
+
+// posix version
+exports.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ if (typeof p !== 'string') {
+ throw new TypeError('Arguments to path.join must be strings');
+ }
+ return p;
+ }).join('/'));
+};
+
+
+// path.relative(from, to)
+// posix version
+exports.relative = function(from, to) {
+ from = exports.resolve(from).substr(1);
+ to = exports.resolve(to).substr(1);
+
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+
+ return outputParts.join('/');
+};
+
+exports.sep = '/';
+exports.delimiter = ':';
+
+exports.dirname = function(path) {
+ var result = splitPath(path),
+ root = result[0],
+ dir = result[1];
+
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+
+ return root + dir;
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPath(path)[2];
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPath(path)[3];
+};
+
+function filter (xs, f) {
+ if (xs.filter) return xs.filter(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (f(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// String.prototype.substr - negative index don't work in IE8
+var substr = 'ab'.substr(-1) === 'b'
+ ? function (str, start, len) { return str.substr(start, len) }
+ : function (str, start, len) {
+ if (start < 0) start = str.length + start;
+ return str.substr(start, len);
+ }
+;
+
+}).call(this,require('_process'))
+},{"_process":12}],12:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],13:[function(require,module,exports){
+// Generated by CoffeeScript 1.9.3
+(function() {
+ var assert, copyOwn, every, find, generate, head, hierarchy, inherited, isEmpty, isEqual, isJavaScriptClass, map, memoize, merge, mro, partial, ref, reject, reparent, some, tail, without,
+ slice = [].slice,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ ref = require('underscore'), head = ref.head, tail = ref.tail, map = ref.map, find = ref.find, some = ref.some, without = ref.without, isEmpty = ref.isEmpty, every = ref.every, memoize = ref.memoize, reject = ref.reject, partial = ref.partial, isEqual = ref.isEqual;
+
+ assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.multi = function() {
+ var bases;
+ bases = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return generate(merge(map(bases, mro).concat([bases])));
+ };
+
+ generate = memoize(function(linearization) {
+ var next, result;
+ next = head(linearization);
+ if (isEqual(linearization, hierarchy(next))) {
+ return next;
+ } else {
+ return result = (function(superClass) {
+ var class1;
+
+ extend(result, superClass);
+
+ function result() {
+ return class1.apply(this, arguments);
+ }
+
+ result.prototype.__mro__ = linearization;
+
+ class1 = reparent(next, result, next.prototype.constructor);
+
+ copyOwn(next, result);
+
+ copyOwn(next.prototype, result.prototype, partial(reparent, next, result));
+
+ return result;
+
+ })(generate(tail(linearization)));
+ }
+ });
+
+ copyOwn = function(from, to, project) {
+ var key, value;
+ if (project == null) {
+ project = function(x) {
+ return x;
+ };
+ }
+ for (key in from) {
+ if (!hasProp.call(from, key)) continue;
+ value = from[key];
+ if (!to.hasOwnProperty(key)) {
+ to[key] = project(value);
+ }
+ }
+ return to;
+ };
+
+ reparent = function(oldklass, newklass, value) {
+ var newsuper, oldsuper, superctor;
+ if (!(value instanceof Function)) {
+ return value;
+ } else if (value === oldklass.prototype.constructor && inherited(oldklass) === Object) {
+ superctor = inherited(newklass).prototype.constructor;
+ return function() {
+ superctor.apply(this, arguments);
+ return value.apply(this, arguments);
+ };
+ } else {
+ newsuper = inherited(newklass).prototype;
+ oldsuper = oldklass.__super__;
+ return function() {
+ oldklass.__super__ = newsuper;
+ try {
+ return value.apply(this, arguments);
+ } finally {
+ oldklass.__super__ = oldsuper;
+ }
+ };
+ }
+ };
+
+ merge = function(inputs) {
+ var next, results;
+ results = [];
+ while (!isEmpty(inputs)) {
+ next = find(map(inputs, head), function(candidate) {
+ return every(inputs, function(input) {
+ return indexOf.call(tail(input), candidate) < 0;
+ });
+ });
+ assert(next != null, "Inconsistent multiple inheritance");
+ inputs = reject(map(inputs, function(lst) {
+ return without(lst, next);
+ }), isEmpty);
+ results.push(next);
+ }
+ return results;
+ };
+
+ isJavaScriptClass = function(cls) {
+ return cls === Array || cls === Boolean || cls === Date || cls === Error || cls === Function || cls === Number || cls === RegExp || cls === String || cls === Object;
+ };
+
+ exports.mro = mro = function(cls) {
+ var result;
+ if ((cls == null) || (cls.prototype == null)) {
+ return [];
+ } else if (!cls.prototype.hasOwnProperty('__mro__')) {
+ result = [cls].concat(mro(inherited(cls)));
+ if (!isJavaScriptClass(cls)) {
+ cls.prototype.__mro__ = result;
+ }
+ return result;
+ } else {
+ return cls.prototype.__mro__;
+ }
+ };
+
+ exports.inherited = inherited = function(cls) {
+ var ref1;
+ return (ref1 = Object.getPrototypeOf(cls.prototype)) != null ? ref1.constructor : void 0;
+ };
+
+ exports.hierarchy = hierarchy = function(cls) {
+ if (cls == null) {
+ return [];
+ } else {
+ return [cls].concat(hierarchy(inherited(cls)));
+ }
+ };
+
+ exports.isinstance = function() {
+ var classes, obj;
+ obj = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.issubclass.apply(exports, [obj != null ? obj.constructor : void 0].concat(slice.call(classes)));
+ };
+
+ exports.issubclass = function() {
+ var classes, klass, linearization;
+ klass = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ linearization = mro(klass);
+ return some(classes, function(cls) {
+ return indexOf.call(linearization, cls) >= 0;
+ });
+ };
+
+}).call(this);
+
+},{"underscore":16}],14:[function(require,module,exports){
+function count(self, substr) {
+ var count = 0
+ var pos = self.indexOf(substr)
+
+ while (pos >= 0) {
+ count += 1
+ pos = self.indexOf(substr, pos + 1)
+ }
+
+ return count
+}
+
+module.exports = count
+},{}],15:[function(require,module,exports){
+/*
+string.js - Copyright (C) 2012-2014, JP Richardson
+*/
+
+!(function() {
+ "use strict";
+
+ var VERSION = '3.1.3';
+
+ var ENTITIES = {};
+
+ // from http://semplicewebsites.com/removing-accents-javascript
+ var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};
+
+//******************************************************************************
+// Added an initialize function which is essentially the code from the S
+// constructor. Now, the S constructor calls this and a new method named
+// setValue calls it as well. The setValue function allows constructors for
+// modules that extend string.js to set the initial value of an object without
+// knowing the internal workings of string.js.
+//
+// Also, all methods which return a new S object now call:
+//
+// return new this.constructor(s);
+//
+// instead of:
+//
+// return new S(s);
+//
+// This allows extended objects to keep their proper instanceOf and constructor.
+//******************************************************************************
+
+ function initialize (object, s) {
+ if (s !== null && s !== undefined) {
+ if (typeof s === 'string')
+ object.s = s;
+ else
+ object.s = s.toString();
+ } else {
+ object.s = s; //null or undefined
+ }
+
+ object.orig = s; //original object, currently only used by toCSV() and toBoolean()
+
+ if (s !== null && s !== undefined) {
+ if (object.__defineGetter__) {
+ object.__defineGetter__('length', function() {
+ return object.s.length;
+ })
+ } else {
+ object.length = s.length;
+ }
+ } else {
+ object.length = -1;
+ }
+ }
+
+ function S(s) {
+ initialize(this, s);
+ }
+
+ var __nsp = String.prototype;
+ var __sp = S.prototype = {
+
+ between: function(left, right) {
+ var s = this.s;
+ var startPos = s.indexOf(left);
+ var endPos = s.indexOf(right, startPos + left.length);
+ if (endPos == -1 && right != null)
+ return new this.constructor('')
+ else if (endPos == -1 && right == null)
+ return new this.constructor(s.substring(startPos + left.length))
+ else
+ return new this.constructor(s.slice(startPos + left.length, endPos));
+ },
+
+ //# modified slightly from https://github.com/epeli/underscore.string
+ camelize: function() {
+ var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) {
+ return (c ? c.toUpperCase() : '');
+ });
+ return new this.constructor(s);
+ },
+
+ capitalize: function() {
+ return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase());
+ },
+
+ charAt: function(index) {
+ return this.s.charAt(index);
+ },
+
+ chompLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ s = s.slice(prefix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ chompRight: function(suffix) {
+ if (this.endsWith(suffix)) {
+ var s = this.s;
+ s = s.slice(0, s.length - suffix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ //#thanks Google
+ collapseWhitespace: function() {
+ var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, '');
+ return new this.constructor(s);
+ },
+
+ contains: function(ss) {
+ return this.s.indexOf(ss) >= 0;
+ },
+
+ count: function(ss) {
+ return require('./_count')(this.s, ss)
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ dasherize: function() {
+ var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ latinise: function() {
+ var s = this.replace(/[^A-Za-z0-9\[\] ]/g, function(x) { return latin_map[x] || x; });
+ return new this.constructor(s);
+ },
+
+ decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js
+ var s = this.s;
+ s = s.replace(/(\d+);?/g, function (_, code) {
+ return String.fromCharCode(code);
+ })
+ .replace(/[xX]([A-Fa-f0-9]+);?/g, function (_, hex) {
+ return String.fromCharCode(parseInt(hex, 16));
+ })
+ .replace(/&([^;\W]+;?)/g, function (m, e) {
+ var ee = e.replace(/;$/, '');
+ var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]);
+
+ if (typeof target === 'number') {
+ return String.fromCharCode(target);
+ }
+ else if (typeof target === 'string') {
+ return target;
+ }
+ else {
+ return m;
+ }
+ })
+
+ return new this.constructor(s);
+ },
+
+ endsWith: function() {
+ var suffixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < suffixes.length; ++i) {
+ var l = this.s.length - suffixes[i].length;
+ if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true;
+ }
+ return false;
+ },
+
+ escapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
+ },
+
+ ensureLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ return this;
+ } else {
+ return new this.constructor(prefix + s);
+ }
+ },
+
+ ensureRight: function(suffix) {
+ var s = this.s;
+ if (this.endsWith(suffix)) {
+ return this;
+ } else {
+ return new this.constructor(s + suffix);
+ }
+ },
+
+ humanize: function() { //modified from underscore.string
+ if (this.s === null || this.s === undefined)
+ return new this.constructor('')
+ var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize()
+ return new this.constructor(s)
+ },
+
+ isAlpha: function() {
+ return !/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase());
+ },
+
+ isAlphaNumeric: function() {
+ return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase());
+ },
+
+ isEmpty: function() {
+ return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s);
+ },
+
+ isLower: function() {
+ return this.isAlpha() && this.s.toLowerCase() === this.s;
+ },
+
+ isNumeric: function() {
+ return !/[^0-9]/.test(this.s);
+ },
+
+ isUpper: function() {
+ return this.isAlpha() && this.s.toUpperCase() === this.s;
+ },
+
+ left: function(N) {
+ if (N >= 0) {
+ var s = this.s.substr(0, N);
+ return new this.constructor(s);
+ } else {
+ return this.right(-N);
+ }
+ },
+
+ lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines
+ return this.replaceAll('\r\n', '\n').s.split('\n');
+ },
+
+ pad: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ len = len - this.s.length;
+ var left = Array(Math.ceil(len / 2) + 1).join(ch);
+ var right = Array(Math.floor(len / 2) + 1).join(ch);
+ return new this.constructor(left + this.s + right);
+ },
+
+ padLeft: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s);
+ },
+
+ padRight: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch));
+ },
+
+ parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what
+ delimiter = delimiter || ',';
+ escape = escape || '\\'
+ if (typeof qualifier == 'undefined')
+ qualifier = '"';
+
+ var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this;
+ var ca = function(i){return self.s.charAt(i)};
+ if (typeof lineDelimiter !== 'undefined') var rows = [];
+
+ if (!qualifier)
+ inField = true;
+
+ while (i < len) {
+ var current = ca(i);
+ switch (current) {
+ case escape:
+ //fix for issues #32 and #35
+ if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) {
+ i += 1;
+ fieldBuffer.push(ca(i));
+ break;
+ }
+ if (escape !== qualifier) break;
+ case qualifier:
+ inField = !inField;
+ break;
+ case delimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ }
+ if (inField && qualifier)
+ fieldBuffer.push(current);
+ else {
+ fields.push(fieldBuffer.join(''))
+ fieldBuffer.length = 0;
+ }
+ break;
+ case lineDelimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ else if (inField) {
+ fieldBuffer.push(current);
+ } else {
+ if (rows) {
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ }
+ break;
+ case ' ':
+ if (inField)
+ fieldBuffer.push(current);
+ break;
+ default:
+ if (inField)
+ fieldBuffer.push(current);
+ else if(current!==qualifier) {
+ fieldBuffer.push(current);
+ inField=true;
+ inUnqualifiedString=true;
+ }
+ break;
+ }
+ i += 1;
+ }
+
+ fields.push(fieldBuffer.join(''));
+ if (rows) {
+ rows.push(fields);
+ return rows;
+ }
+ return fields;
+ },
+
+ replaceAll: function(ss, r) {
+ //var s = this.s.replace(new RegExp(ss, 'g'), r);
+ var s = this.s.split(ss).join(r)
+ return new this.constructor(s);
+ },
+
+ strip: function() {
+ var ss = this.s;
+ for(var i= 0, n=arguments.length; i= 0) {
+ var s = this.s.substr(this.s.length - N, N);
+ return new this.constructor(s);
+ } else {
+ return this.left(-N);
+ }
+ },
+
+ setValue: function (s) {
+ initialize(this, s);
+ return this;
+ },
+
+ slugify: function() {
+ var sl = (new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s;
+ if (sl.charAt(0) === '-')
+ sl = sl.substr(1);
+ return new this.constructor(sl);
+ },
+
+ startsWith: function() {
+ var prefixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < prefixes.length; ++i) {
+ if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true;
+ }
+ return false;
+ },
+
+ stripPunctuation: function() {
+ //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
+ return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
+ },
+
+ stripTags: function() { //from sugar.js
+ var s = this.s, args = arguments.length > 0 ? arguments : [''];
+ multiArgs(args, function(tag) {
+ s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), '');
+ });
+ return new this.constructor(s);
+ },
+
+ template: function(values, opening, closing) {
+ var s = this.s
+ var opening = opening || Export.TMPL_OPEN
+ var closing = closing || Export.TMPL_CLOSE
+
+ var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var r = new RegExp(open + '(.+?)' + close, 'g')
+ //, r = /\{\{(.+?)\}\}/g
+ var matches = s.match(r) || [];
+
+ matches.forEach(function(match) {
+ var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }}
+ var value = typeof values[key] == 'undefined' ? '' : values[key];
+ s = s.replace(match, value);
+ });
+ return new this.constructor(s);
+ },
+
+ times: function(n) {
+ return new this.constructor(new Array(n + 1).join(this.s));
+ },
+
+ toBoolean: function() {
+ if (typeof this.orig === 'string') {
+ var s = this.s.toLowerCase();
+ return s === 'true' || s === 'yes' || s === 'on' || s === '1';
+ } else
+ return this.orig === true || this.orig === 1;
+ },
+
+ toFloat: function(precision) {
+ var num = parseFloat(this.s)
+ if (precision)
+ return parseFloat(num.toFixed(precision))
+ else
+ return num
+ },
+
+ toInt: function() { //thanks Google
+ // If the string starts with '0x' or '-0x', parse as hex.
+ return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10)
+ },
+
+ trim: function() {
+ var s;
+ if (typeof __nsp.trim === 'undefined')
+ s = this.s.replace(/(^\s*|\s*$)/g, '')
+ else
+ s = this.s.trim()
+ return new this.constructor(s);
+ },
+
+ trimLeft: function() {
+ var s;
+ if (__nsp.trimLeft)
+ s = this.s.trimLeft();
+ else
+ s = this.s.replace(/(^\s*)/g, '');
+ return new this.constructor(s);
+ },
+
+ trimRight: function() {
+ var s;
+ if (__nsp.trimRight)
+ s = this.s.trimRight();
+ else
+ s = this.s.replace(/\s+$/, '');
+ return new this.constructor(s);
+ },
+
+ truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz
+ var str = this.s;
+
+ length = ~~length;
+ pruneStr = pruneStr || '...';
+
+ if (str.length <= length) return new this.constructor(str);
+
+ var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
+ template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
+
+ if (template.slice(template.length-2).match(/\w\w/))
+ template = template.replace(/\s*\S+$/, '');
+ else
+ template = new S(template.slice(0, template.length-1)).trimRight().s;
+
+ return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr);
+ },
+
+ toCSV: function() {
+ var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false;
+ var dataArray = [];
+
+ function hasVal(it) {
+ return it !== null && it !== '';
+ }
+
+ if (typeof arguments[0] === 'object') {
+ delim = arguments[0].delimiter || delim;
+ delim = arguments[0].separator || delim;
+ qualifier = arguments[0].qualifier || qualifier;
+ encloseNumbers = !!arguments[0].encloseNumbers;
+ escape = arguments[0].escape || escape;
+ keys = !!arguments[0].keys;
+ } else if (typeof arguments[0] === 'string') {
+ delim = arguments[0];
+ }
+
+ if (typeof arguments[1] === 'string')
+ qualifier = arguments[1];
+
+ if (arguments[1] === null)
+ qualifier = null;
+
+ if (this.orig instanceof Array)
+ dataArray = this.orig;
+ else { //object
+ for (var key in this.orig)
+ if (this.orig.hasOwnProperty(key))
+ if (keys)
+ dataArray.push(key);
+ else
+ dataArray.push(this.orig[key]);
+ }
+
+ var rep = escape + qualifier;
+ var buildString = [];
+ for (var i = 0; i < dataArray.length; ++i) {
+ var shouldQualify = hasVal(qualifier)
+ if (typeof dataArray[i] == 'number')
+ shouldQualify &= encloseNumbers;
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (dataArray[i] !== null && dataArray[i] !== undefined) {
+ var d = new S(dataArray[i]).replaceAll(qualifier, rep).s;
+ buildString.push(d);
+ } else
+ buildString.push('')
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (delim)
+ buildString.push(delim);
+ }
+
+ //chop last delim
+ //console.log(buildString.length)
+ buildString.length = buildString.length - 1;
+ return new this.constructor(buildString.join(''));
+ },
+
+ toString: function() {
+ return this.s;
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ underscore: function() {
+ var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/([A-Z\d]+)([A-Z][a-z])/,'$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ unescapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){
+ var match;
+
+ if (entityCode in escapeChars) {
+ return escapeChars[entityCode];
+ } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
+ return String.fromCharCode(parseInt(match[1], 16));
+ } else if (match = entityCode.match(/^#(\d+)$/)) {
+ return String.fromCharCode(~~match[1]);
+ } else {
+ return entity;
+ }
+ }));
+ },
+
+ valueOf: function() {
+ return this.s.valueOf();
+ },
+
+ //#Added a New Function called wrapHTML.
+ wrapHTML: function (tagName, tagAttrs) {
+ var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = '';
+ if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"';
+ s = wrapped.concat('<', el, elAttr, '>', this, '', el, '>');
+ return new this.constructor(s);
+ }
+ }
+
+ var methodsAdded = [];
+ function extendPrototype() {
+ for (var name in __sp) {
+ (function(name){
+ var func = __sp[name];
+ if (!__nsp.hasOwnProperty(name)) {
+ methodsAdded.push(name);
+ __nsp[name] = function() {
+ String.prototype.s = this;
+ return func.apply(this, arguments);
+ }
+ }
+ })(name);
+ }
+ }
+
+ function restorePrototype() {
+ for (var i = 0; i < methodsAdded.length; ++i)
+ delete String.prototype[methodsAdded[i]];
+ methodsAdded.length = 0;
+ }
+
+
+/*************************************
+/* Attach Native JavaScript String Properties
+/*************************************/
+
+ var nativeProperties = getNativeStringProperties();
+ for (var name in nativeProperties) {
+ (function(name) {
+ var stringProp = __nsp[name];
+ if (typeof stringProp == 'function') {
+ //console.log(stringProp)
+ if (!__sp[name]) {
+ if (nativeProperties[name] === 'string') {
+ __sp[name] = function() {
+ //console.log(name)
+ return new this.constructor(stringProp.apply(this, arguments));
+ }
+ } else {
+ __sp[name] = stringProp;
+ }
+ }
+ }
+ })(name);
+ }
+
+
+/*************************************
+/* Function Aliases
+/*************************************/
+
+ __sp.repeat = __sp.times;
+ __sp.include = __sp.contains;
+ __sp.toInteger = __sp.toInt;
+ __sp.toBool = __sp.toBoolean;
+ __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML'
+
+
+//******************************************************************************
+// Set the constructor. Without this, string.js objects are instances of
+// Object instead of S.
+//******************************************************************************
+
+ __sp.constructor = S;
+
+
+/*************************************
+/* Private Functions
+/*************************************/
+
+ function getNativeStringProperties() {
+ var names = getNativeStringPropertyNames();
+ var retObj = {};
+
+ for (var i = 0; i < names.length; ++i) {
+ var name = names[i];
+ var func = __nsp[name];
+ try {
+ // #127: pass extra parameter to keep shelljs happy
+ var type = typeof func.apply('test', ['string']);
+ retObj[name] = type;
+ } catch (e) {}
+ }
+ return retObj;
+ }
+
+ function getNativeStringPropertyNames() {
+ var results = [];
+ if (Object.getOwnPropertyNames) {
+ results = Object.getOwnPropertyNames(__nsp);
+ results.splice(results.indexOf('valueOf'), 1);
+ results.splice(results.indexOf('toString'), 1);
+ return results;
+ } else { //meant for legacy cruft, this could probably be made more efficient
+ var stringNames = {};
+ var objectNames = [];
+ for (var name in String.prototype)
+ stringNames[name] = name;
+
+ for (var name in Object.prototype)
+ delete stringNames[name];
+
+ //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names
+ for (var name in stringNames) {
+ results.push(name);
+ }
+ return results;
+ }
+ }
+
+ function Export(str) {
+ return new S(str);
+ };
+
+ //attach exports to StringJSWrapper
+ Export.extendPrototype = extendPrototype;
+ Export.restorePrototype = restorePrototype;
+ Export.VERSION = VERSION;
+ Export.TMPL_OPEN = '{{';
+ Export.TMPL_CLOSE = '}}';
+ Export.ENTITIES = ENTITIES;
+
+
+
+/*************************************
+/* Exports
+/*************************************/
+
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
+ module.exports = Export;
+
+ } else {
+
+ if(typeof define === "function" && define.amd) {
+ define([], function() {
+ return Export;
+ });
+ } else {
+ window.S = Export;
+ }
+ }
+
+
+/*************************************
+/* 3rd Party Private Functions
+/*************************************/
+
+ //from sugar.js
+ function multiArgs(args, fn) {
+ var result = [], i;
+ for(i = 0; i < args.length; i++) {
+ result.push(args[i]);
+ if(fn) fn.call(args, args[i], i);
+ }
+ return result;
+ }
+
+ //from underscore.string
+ var escapeChars = {
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ apos: "'",
+ amp: '&'
+ };
+
+ function escapeRegExp (s) {
+ // most part from https://github.com/skulpt/skulpt/blob/ecaf75e69c2e539eff124b2ab45df0b01eaf2295/src/str.js#L242
+ var c;
+ var i;
+ var ret = [];
+ var re = /^[A-Za-z0-9]+$/;
+ s = ensureString(s);
+ for (i = 0; i < s.length; ++i) {
+ c = s.charAt(i);
+
+ if (re.test(c)) {
+ ret.push(c);
+ }
+ else {
+ if (c === "\\000") {
+ ret.push("\\000");
+ }
+ else {
+ ret.push("\\" + c);
+ }
+ }
+ }
+ return ret.join("");
+ }
+
+ function ensureString(string) {
+ return string == null ? '' : '' + string;
+ }
+
+ //from underscore.string
+ var reversedEscapeChars = {};
+ for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
+
+ ENTITIES = {
+ "amp" : "&",
+ "gt" : ">",
+ "lt" : "<",
+ "quot" : "\"",
+ "apos" : "'",
+ "AElig" : 198,
+ "Aacute" : 193,
+ "Acirc" : 194,
+ "Agrave" : 192,
+ "Aring" : 197,
+ "Atilde" : 195,
+ "Auml" : 196,
+ "Ccedil" : 199,
+ "ETH" : 208,
+ "Eacute" : 201,
+ "Ecirc" : 202,
+ "Egrave" : 200,
+ "Euml" : 203,
+ "Iacute" : 205,
+ "Icirc" : 206,
+ "Igrave" : 204,
+ "Iuml" : 207,
+ "Ntilde" : 209,
+ "Oacute" : 211,
+ "Ocirc" : 212,
+ "Ograve" : 210,
+ "Oslash" : 216,
+ "Otilde" : 213,
+ "Ouml" : 214,
+ "THORN" : 222,
+ "Uacute" : 218,
+ "Ucirc" : 219,
+ "Ugrave" : 217,
+ "Uuml" : 220,
+ "Yacute" : 221,
+ "aacute" : 225,
+ "acirc" : 226,
+ "aelig" : 230,
+ "agrave" : 224,
+ "aring" : 229,
+ "atilde" : 227,
+ "auml" : 228,
+ "ccedil" : 231,
+ "eacute" : 233,
+ "ecirc" : 234,
+ "egrave" : 232,
+ "eth" : 240,
+ "euml" : 235,
+ "iacute" : 237,
+ "icirc" : 238,
+ "igrave" : 236,
+ "iuml" : 239,
+ "ntilde" : 241,
+ "oacute" : 243,
+ "ocirc" : 244,
+ "ograve" : 242,
+ "oslash" : 248,
+ "otilde" : 245,
+ "ouml" : 246,
+ "szlig" : 223,
+ "thorn" : 254,
+ "uacute" : 250,
+ "ucirc" : 251,
+ "ugrave" : 249,
+ "uuml" : 252,
+ "yacute" : 253,
+ "yuml" : 255,
+ "copy" : 169,
+ "reg" : 174,
+ "nbsp" : 160,
+ "iexcl" : 161,
+ "cent" : 162,
+ "pound" : 163,
+ "curren" : 164,
+ "yen" : 165,
+ "brvbar" : 166,
+ "sect" : 167,
+ "uml" : 168,
+ "ordf" : 170,
+ "laquo" : 171,
+ "not" : 172,
+ "shy" : 173,
+ "macr" : 175,
+ "deg" : 176,
+ "plusmn" : 177,
+ "sup1" : 185,
+ "sup2" : 178,
+ "sup3" : 179,
+ "acute" : 180,
+ "micro" : 181,
+ "para" : 182,
+ "middot" : 183,
+ "cedil" : 184,
+ "ordm" : 186,
+ "raquo" : 187,
+ "frac14" : 188,
+ "frac12" : 189,
+ "frac34" : 190,
+ "iquest" : 191,
+ "times" : 215,
+ "divide" : 247,
+ "OElig;" : 338,
+ "oelig;" : 339,
+ "Scaron;" : 352,
+ "scaron;" : 353,
+ "Yuml;" : 376,
+ "fnof;" : 402,
+ "circ;" : 710,
+ "tilde;" : 732,
+ "Alpha;" : 913,
+ "Beta;" : 914,
+ "Gamma;" : 915,
+ "Delta;" : 916,
+ "Epsilon;" : 917,
+ "Zeta;" : 918,
+ "Eta;" : 919,
+ "Theta;" : 920,
+ "Iota;" : 921,
+ "Kappa;" : 922,
+ "Lambda;" : 923,
+ "Mu;" : 924,
+ "Nu;" : 925,
+ "Xi;" : 926,
+ "Omicron;" : 927,
+ "Pi;" : 928,
+ "Rho;" : 929,
+ "Sigma;" : 931,
+ "Tau;" : 932,
+ "Upsilon;" : 933,
+ "Phi;" : 934,
+ "Chi;" : 935,
+ "Psi;" : 936,
+ "Omega;" : 937,
+ "alpha;" : 945,
+ "beta;" : 946,
+ "gamma;" : 947,
+ "delta;" : 948,
+ "epsilon;" : 949,
+ "zeta;" : 950,
+ "eta;" : 951,
+ "theta;" : 952,
+ "iota;" : 953,
+ "kappa;" : 954,
+ "lambda;" : 955,
+ "mu;" : 956,
+ "nu;" : 957,
+ "xi;" : 958,
+ "omicron;" : 959,
+ "pi;" : 960,
+ "rho;" : 961,
+ "sigmaf;" : 962,
+ "sigma;" : 963,
+ "tau;" : 964,
+ "upsilon;" : 965,
+ "phi;" : 966,
+ "chi;" : 967,
+ "psi;" : 968,
+ "omega;" : 969,
+ "thetasym;" : 977,
+ "upsih;" : 978,
+ "piv;" : 982,
+ "ensp;" : 8194,
+ "emsp;" : 8195,
+ "thinsp;" : 8201,
+ "zwnj;" : 8204,
+ "zwj;" : 8205,
+ "lrm;" : 8206,
+ "rlm;" : 8207,
+ "ndash;" : 8211,
+ "mdash;" : 8212,
+ "lsquo;" : 8216,
+ "rsquo;" : 8217,
+ "sbquo;" : 8218,
+ "ldquo;" : 8220,
+ "rdquo;" : 8221,
+ "bdquo;" : 8222,
+ "dagger;" : 8224,
+ "Dagger;" : 8225,
+ "bull;" : 8226,
+ "hellip;" : 8230,
+ "permil;" : 8240,
+ "prime;" : 8242,
+ "Prime;" : 8243,
+ "lsaquo;" : 8249,
+ "rsaquo;" : 8250,
+ "oline;" : 8254,
+ "frasl;" : 8260,
+ "euro;" : 8364,
+ "image;" : 8465,
+ "weierp;" : 8472,
+ "real;" : 8476,
+ "trade;" : 8482,
+ "alefsym;" : 8501,
+ "larr;" : 8592,
+ "uarr;" : 8593,
+ "rarr;" : 8594,
+ "darr;" : 8595,
+ "harr;" : 8596,
+ "crarr;" : 8629,
+ "lArr;" : 8656,
+ "uArr;" : 8657,
+ "rArr;" : 8658,
+ "dArr;" : 8659,
+ "hArr;" : 8660,
+ "forall;" : 8704,
+ "part;" : 8706,
+ "exist;" : 8707,
+ "empty;" : 8709,
+ "nabla;" : 8711,
+ "isin;" : 8712,
+ "notin;" : 8713,
+ "ni;" : 8715,
+ "prod;" : 8719,
+ "sum;" : 8721,
+ "minus;" : 8722,
+ "lowast;" : 8727,
+ "radic;" : 8730,
+ "prop;" : 8733,
+ "infin;" : 8734,
+ "ang;" : 8736,
+ "and;" : 8743,
+ "or;" : 8744,
+ "cap;" : 8745,
+ "cup;" : 8746,
+ "int;" : 8747,
+ "there4;" : 8756,
+ "sim;" : 8764,
+ "cong;" : 8773,
+ "asymp;" : 8776,
+ "ne;" : 8800,
+ "equiv;" : 8801,
+ "le;" : 8804,
+ "ge;" : 8805,
+ "sub;" : 8834,
+ "sup;" : 8835,
+ "nsub;" : 8836,
+ "sube;" : 8838,
+ "supe;" : 8839,
+ "oplus;" : 8853,
+ "otimes;" : 8855,
+ "perp;" : 8869,
+ "sdot;" : 8901,
+ "lceil;" : 8968,
+ "rceil;" : 8969,
+ "lfloor;" : 8970,
+ "rfloor;" : 8971,
+ "lang;" : 9001,
+ "rang;" : 9002,
+ "loz;" : 9674,
+ "spades;" : 9824,
+ "clubs;" : 9827,
+ "hearts;" : 9829,
+ "diams;" : 9830
+ }
+
+
+}).call(this);
+
+},{"./_count":14}],16:[function(require,module,exports){
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
+
+},{}],"/home/raskolnikov/dev/mixco/script/korg_nanokontrol2.mixco":[function(require,module,exports){
+var assert, b, c, mixco, v;
+
+mixco = require('mixco');
+
+assert = mixco.util.assert;
+
+c = mixco.control;
+
+b = mixco.behaviour;
+
+v = mixco.value;
+
+mixco.script.register(module, {
+ info: {
+ name: '[mixco] Korg Nanokontrol 2',
+ author: 'Juan Pedro Bolivar Puente ',
+ wiki: 'https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html',
+ forums: 'https://github.com/arximboldi/mixco/issues',
+ description: "Controller mapping for Korg Nanokontrol 2. Unlike\nother scripts that are oriented as a secondary\ncontroller, this provides basic deck controls, being\nusable as primary interface."
+ },
+ constructor: function() {
+ var g;
+ this.cycle = b.modifier();
+ c.control(0x2e).does(this.cycle);
+ this.backButton = c.control(0x3a);
+ this.fwdButton = c.control(0x3b);
+ this.nudgeDownButton = c.control(0x2b);
+ this.nudgeUpButton = c.control(0x2c);
+ this.marker = b.modifier();
+ c.control(0x3C).does(this.marker);
+ g = "[Playlist]";
+ c.control(0x3D).when(this.marker, g, "SelectPrevPlaylist")["else"](g, "SelectPrevTrack");
+ c.control(0x3E).when(this.marker, g, "SelectNextPlaylist")["else"](g, "SelectNextTrack");
+ this.loadTrack = c.control(0x2a);
+ this.sync = c.control(0x29);
+ this.syncTempo = c.control(0x2d);
+ g = "[Master]";
+ c.input(0x06).does(g, "headVolume");
+ c.input(0x05).does(g, "headMix");
+ c.input(0x02).does(b.soft(g, "crossfader"));
+ c.input(0x01).does(b.soft(g, "balance"));
+ this.decks = b.chooser();
+ this.addDeck(0);
+ return this.addDeck(1);
+ },
+ addDeck: function(i) {
+ var chooseCycle, g, offset;
+ assert(i === 0 || i === 1);
+ g = "[Channel" + (i + 1) + "]";
+ offset = i === 0 ? [3, 2, 1, 0] : [4, 5, 6, 7];
+ c.input(0x10 + offset[0]).does(g, "filterLow");
+ c.input(0x10 + offset[1]).does(g, "filterMid");
+ c.input(0x10 + offset[2]).does(g, "filterHigh");
+ c.input(0x10 + offset[3]).does(b.soft(g, "pregain"));
+ c.control(0x20 + offset[0]).does(this.decks.add(g, "pfl"));
+ c.control(0x30 + offset[0]).does(g, "cue_default", g, "cue_indicator");
+ c.control(0x40 + offset[0]).does(g, "play");
+ c.input(0x00 + offset[0]).does(g, "volume");
+ c.control(0x20 + offset[3]).does(g, "bpm_tap", g, "beat_active");
+ c.control(0x30 + offset[3]).does(g, "keylock");
+ c.control(0x40 + offset[3]).does(g, "beats_translate_curpos");
+ c.input(0x00 + offset[3]).does(b.soft(g, "rate"));
+ c.control(0x20 + offset[1]).when(this.cycle, g, "hotcue_1_activate", g, "hotcue_1_enabled")["else"].when(this.marker, g, "hotcue_1_clear", g, "hotcue_1_enabled")["else"](g, "beatloop_2_toggle", g, "beatloop_2_enabled");
+ c.control(0x20 + offset[2]).when(this.cycle, g, "hotcue_2_activate", g, "hotcue_2_enabled")["else"].when(this.marker, g, "hotcue_2_clear", g, "hotcue_2_enabled")["else"](g, "beatloop_4_toggle", g, "beatloop_4_enabled");
+ c.control(0x30 + offset[1]).when(this.cycle, g, "hotcue_3_activate", g, "hotcue_3_enabled")["else"].when(this.marker, g, "hotcue_3_clear", g, "hotcue_3_enabled")["else"](g, "beatloop_8_toggle", g, "beatloop_8_enabled");
+ c.control(0x30 + offset[2]).when(this.cycle, g, "hotcue_4_activate", g, "hotcue_4_enabled")["else"].when(this.marker, g, "hotcue_4_clear", g, "hotcue_4_enabled")["else"](g, "beatloop_16_toggle", g, "beatloop_16_enabled");
+ c.control(0x40 + offset[1]).when(this.cycle, g, "hotcue_5_activate", g, "hotcue_5_enabled")["else"].when(this.marker, g, "hotcue_5_clear", g, "hotcue_5_enabled")["else"](g, "loop_halve");
+ c.control(0x40 + offset[2]).when(this.cycle, g, "hotcue_6_activate", g, "hotcue_6_enabled")["else"].when(this.marker, g, "hotcue_6_clear", g, "hotcue_6_enabled")["else"](g, "loop_double");
+ chooseCycle = v.and(this.cycle, this.decks.activator(i));
+ this.nudgeUpButton.when(chooseCycle, b.toggle(0, 0.5, g, "wheel"))["else"].when(this.decks.activator(i), b.toggle(0, 0.1, g, "wheel"));
+ this.nudgeDownButton.when(chooseCycle, b.toggle(0, -0.5, g, "wheel"))["else"].when(this.decks.activator(i), b.toggle(0, -0.1, g, "wheel"));
+ this.fwdButton.when(this.decks.activator(i), g, "fwd");
+ this.backButton.when(this.decks.activator(i), g, "back");
+ this.loadTrack.when(this.decks.activator(i), g, "LoadSelectedTrack");
+ this.sync.when(this.decks.activator(i), g, "sync_enabled");
+ return this.syncTempo.when(this.decks.activator(i), g, "beatsync");
+ },
+ init: function() {
+ return this.decks.activate(0);
+ }
+});
+
+
+},{"mixco":2}],17:[function(require,module,exports){
+var _, assert, bind, copy, events, extend, factory, indent, isinstance, makeOptionsChooser, map, multi, option, ref, ref1, ref2, toOption, transform, value,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+transform = require('./transform');
+
+value = require('./value');
+
+ref = require('./util'), indent = ref.indent, assert = ref.assert, factory = ref.factory, copy = ref.copy;
+
+ref1 = require('heterarchy'), multi = ref1.multi, isinstance = ref1.isinstance;
+
+_ = (ref2 = require('underscore'), extend = ref2.extend, bind = ref2.bind, map = ref2.map, ref2);
+
+exports.Actor = (function(superClass) {
+ extend1(Actor, superClass);
+
+ function Actor() {
+ return Actor.__super__.constructor.apply(this, arguments);
+ }
+
+ Actor.prototype.send = void 0;
+
+ return Actor;
+
+})(events.EventEmitter);
+
+toOption = function(option) {
+ var result;
+ result = option;
+ if (isinstance(option, Function)) {
+ result = {
+ transform: option
+ };
+ }
+ if ((result.transform != null) && (result.process == null)) {
+ result.process = result.transform.length === 1 ? function(ev, b) {
+ return ev.value = this.transform(ev.value);
+ } : function(ev, b) {
+ return ev.value = this.transform(ev.value, b.midiValue);
+ };
+ }
+ return result;
+};
+
+option = exports.option = (function() {
+ var add, result, rot64;
+ result = {};
+ add = function() {
+ var desc, i, mixxxName, name, names, option;
+ names = 2 <= arguments.length ? slice.call(arguments, 0, i = arguments.length - 1) : (i = 0, []), option = arguments[i++];
+ mixxxName = names[0], name = names[1];
+ desc = toOption(option);
+ desc.name = mixxxName;
+ result[name != null ? name : mixxxName] = desc;
+ return result;
+ };
+ rot64 = function(sign) {
+ return function(v1, v0) {
+ var diff;
+ diff = v1 - (64..diff = diff === -1 || diff === 1 ? diff / 16.0 : diff - diff.sign());
+ return (v0 + diff * sign).clamp(0, 127);
+ };
+ };
+ add('invert', function(v) {
+ return 127.0 - v;
+ });
+ add('rot64', rot64(1));
+ add('rot64inv', rot64(-1));
+ add('rot64fast', function(v1, v0) {
+ return (v0 + (v1 - 64) * 1.5).clamp(0, 127);
+ });
+ add('diff', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+})();
+
+exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+};
+
+exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+})(value.Value);
+
+exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+})(exports.Behaviour);
+
+exports.call = factory(exports.Call);
+
+exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+})(exports.Behaviour);
+
+exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+})(exports.Output);
+
+exports.transform = factory(exports.Transform);
+
+exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+};
+
+exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+};
+
+exports.switch_ = exports["switch"];
+
+exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+})(exports.Behaviour);
+
+exports.mapIn = factory(exports.MapIn);
+
+exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+})(exports.Output);
+
+exports.mapOut = factory(exports.MapOut);
+
+exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+})(multi(exports.MapIn, exports.MapOut));
+
+exports.map = factory(exports.Map);
+
+exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+};
+
+exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+};
+
+exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+};
+
+exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+};
+
+exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+})(exports.Output);
+
+exports.chooser = factory(exports.Chooser);
+
+exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+})(exports.Behaviour);
+
+exports.when = factory(exports.When);
+
+exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+})(exports.Output);
+
+exports.action = factory(exports.Action);
+
+exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+};
+
+exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+};
+
+exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+};
+
+exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+};
+
+exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+};
+
+exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+};
+
+
+},{"./transform":21,"./util":22,"./value":23,"events":10,"heterarchy":13,"underscore":16}],18:[function(require,module,exports){
+var assert, exports, konsole;
+
+assert = require('./util').assert;
+
+konsole = this;
+
+exports = konsole;
+
+if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+}
+
+if (konsole.info == null) {
+ konsole.info = konsole.log;
+}
+
+if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+}
+
+if (konsole.error == null) {
+ konsole.error = konsole.log;
+}
+
+if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+}
+
+if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+}
+
+if (konsole.assert == null) {
+ konsole.assert = assert;
+}
+
+
+},{"./util":22}],19:[function(require,module,exports){
+var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+multi = require('heterarchy').multi;
+
+ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+behaviour = require('./behaviour');
+
+ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+exports.MIDI_CC = MIDI_CC = 0xB;
+
+exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+};
+
+exports.midiId = midiId;
+
+pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+};
+
+noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+};
+
+noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+};
+
+ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+};
+
+exports.pbIds = pbIds;
+
+exports.noteOnIds = noteOnIds;
+
+exports.noteIds = noteIds;
+
+exports.ccIds = ccIds;
+
+exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+};
+
+exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+})(behaviour.Actor);
+
+exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+})(exports.Control);
+
+exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+})(exports.Control);
+
+exports.input = factory(exports.InControl);
+
+exports.output = factory(exports.OutControl);
+
+exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+})(multi(exports.InControl, exports.OutControl));
+
+exports.control = factory(exports.InOutControl);
+
+
+},{"./behaviour":17,"./util":22,"heterarchy":13,"underscore":16}],20:[function(require,module,exports){
+(function (process){
+var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+Control = require('./control').Control;
+
+ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+require('./console');
+
+basename = require('path').basename;
+
+S = require('string');
+
+_ = require('underscore');
+
+exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+};
+
+exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+};
+
+exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+};
+
+exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+})();
+
+
+}).call(this,require('_process'))
+},{"./console":18,"./control":19,"./util":22,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],21:[function(require,module,exports){
+var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+exports.identity = function(v) {
+ return v;
+};
+
+exports.identity.inverse = exports.identity;
+
+exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+};
+
+exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+};
+
+exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+};
+
+exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+};
+
+exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+};
+
+exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.identityT = identityT = exports.transformI(exports.identity);
+
+exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+};
+
+exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+};
+
+exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+};
+
+
+},{}],22:[function(require,module,exports){
+Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+};
+
+Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+};
+
+Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+};
+
+Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+};
+
+exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+};
+
+exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+};
+
+exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+};
+
+exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+};
+
+exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+};
+
+exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+};
+
+exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+};
+
+exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+};
+
+exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+};
+
+
+},{}],23:[function(require,module,exports){
+var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+util = require('./util');
+
+factory = util.factory;
+
+exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+})(events.EventEmitter);
+
+exports.value = factory(exports.Value);
+
+exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+})();
+
+exports["const"] = factory(exports.Const);
+
+exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+})(exports.Value);
+
+exports.reduce = factory(exports.Reduce);
+
+exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+})(exports.Value);
+
+exports.transform = factory(exports.Transform);
+
+exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+};
+
+
+},{"./util":22,"events":10}]},{},[1]);
+
+korg_nanokontrol2 = require('/home/raskolnikov/dev/mixco/script/korg_nanokontrol2.mixco').korg_nanokontrol2;
+/* End of Mixco generated script */
\ No newline at end of file
diff --git a/res/controllers/korg_nanokontrol2.mixco.output.midi.xml b/res/controllers/korg_nanokontrol2.mixco.output.midi.xml
new file mode 100644
index 000000000000..59ba1fd706bb
--- /dev/null
+++ b/res/controllers/korg_nanokontrol2.mixco.output.midi.xml
@@ -0,0 +1,590 @@
+
+
+
+ Korg Nanokontrol 2 (alternative)
+ Juan Pedro Bolivar Puente <raskolnikov@gnu.org>
+ Controller mapping for Korg Nanokontrol 2. Unlike
+other scripts that are oriented as a secondary
+controller, this provides basic deck controls, being
+usable as primary interface.
+ https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html
+ https://github.com/arximboldi/mixco/issues
+
+
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x2e
+ 0xb0
+ 0x2e
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x3a
+ 0xb0
+ 0x3a
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x3b
+ 0xb0
+ 0x3b
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x2b
+ 0xb0
+ 0x2b
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x2c
+ 0xb0
+ 0x2c
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x3c
+ 0xb0
+ 0x3c
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x3d
+ 0xb0
+ 0x3d
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x3e
+ 0xb0
+ 0x3e
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x2a
+ 0xb0
+ 0x2a
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x29
+ 0xb0
+ 0x29
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x2d
+ 0xb0
+ 0x2d
+
+
+
+
+
+ [Master]
+ headVolume
+ 0xb0
+ 0x6
+
+
+
+
+
+ [Master]
+ headMix
+ 0xb0
+ 0x5
+
+
+
+
+
+ [Master]
+ crossfader
+ 0xb0
+ 0x2
+
+
+
+
+
+ [Master]
+ balance
+ 0xb0
+ 0x1
+
+
+
+
+
+ [Channel1]
+ filterLow
+ 0xb0
+ 0x13
+
+
+
+
+
+ [Channel1]
+ filterMid
+ 0xb0
+ 0x12
+
+
+
+
+
+ [Channel1]
+ filterHigh
+ 0xb0
+ 0x11
+
+
+
+
+
+ [Channel1]
+ pregain
+ 0xb0
+ 0x10
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x23
+ 0xb0
+ 0x23
+
+
+
+
+
+ [Channel1]
+ cue_default
+ 0xb0
+ 0x33
+
+
+
+
+
+ [Channel1]
+ play
+ 0xb0
+ 0x43
+
+
+
+
+
+ [Channel1]
+ volume
+ 0xb0
+ 0x3
+
+
+
+
+
+ [Channel1]
+ bpm_tap
+ 0xb0
+ 0x20
+
+
+
+
+
+ [Channel1]
+ keylock
+ 0xb0
+ 0x30
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0xb0
+ 0x40
+
+
+
+
+
+ [Channel1]
+ rate
+ 0xb0
+ 0x0
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x22
+ 0xb0
+ 0x22
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x21
+ 0xb0
+ 0x21
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x32
+ 0xb0
+ 0x32
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x31
+ 0xb0
+ 0x31
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x42
+ 0xb0
+ 0x42
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x41
+ 0xb0
+ 0x41
+
+
+
+
+
+ [Channel2]
+ filterLow
+ 0xb0
+ 0x14
+
+
+
+
+
+ [Channel2]
+ filterMid
+ 0xb0
+ 0x15
+
+
+
+
+
+ [Channel2]
+ filterHigh
+ 0xb0
+ 0x16
+
+
+
+
+
+ [Channel2]
+ pregain
+ 0xb0
+ 0x17
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x24
+ 0xb0
+ 0x24
+
+
+
+
+
+ [Channel2]
+ cue_default
+ 0xb0
+ 0x34
+
+
+
+
+
+ [Channel2]
+ play
+ 0xb0
+ 0x44
+
+
+
+
+
+ [Channel2]
+ volume
+ 0xb0
+ 0x4
+
+
+
+
+
+ [Channel2]
+ bpm_tap
+ 0xb0
+ 0x27
+
+
+
+
+
+ [Channel2]
+ keylock
+ 0xb0
+ 0x37
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0xb0
+ 0x47
+
+
+
+
+
+ [Channel2]
+ rate
+ 0xb0
+ 0x7
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x25
+ 0xb0
+ 0x25
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x26
+ 0xb0
+ 0x26
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x35
+ 0xb0
+ 0x35
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x36
+ 0xb0
+ 0x36
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x45
+ 0xb0
+ 0x45
+
+
+
+
+
+ [Master]
+ korg_nanokontrol2.__handle_xb0_x46
+ 0xb0
+ 0x46
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/controllers/maudio_xponent.mixco.output.js b/res/controllers/maudio_xponent.mixco.output.js
new file mode 100644
index 000000000000..826896f03a19
--- /dev/null
+++ b/res/controllers/maudio_xponent.mixco.output.js
@@ -0,0 +1,8271 @@
+/*
+ * File generated with Mixco framework version: 2.0.2
+ * More info at:
+ */
+
+MIXCO_SCRIPT_FILENAME = '/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco.litcoffee';
+
+require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+ })();
+
+ exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+ };
+
+ exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+ })(value.Value);
+
+ exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+ })(exports.Behaviour);
+
+ exports.call = factory(exports.Call);
+
+ exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+ })(exports.Behaviour);
+
+ exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+ })(exports.Output);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+ };
+
+ exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+ };
+
+ exports.switch_ = exports["switch"];
+
+ exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+ })(exports.Behaviour);
+
+ exports.mapIn = factory(exports.MapIn);
+
+ exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+ })(exports.Output);
+
+ exports.mapOut = factory(exports.MapOut);
+
+ exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+ })(multi(exports.MapIn, exports.MapOut));
+
+ exports.map = factory(exports.Map);
+
+ exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+ };
+
+ exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+ };
+
+ exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+ };
+
+ exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+ };
+
+ exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+ })(exports.Output);
+
+ exports.chooser = factory(exports.Chooser);
+
+ exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+ })(exports.Behaviour);
+
+ exports.when = factory(exports.When);
+
+ exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+ })(exports.Output);
+
+ exports.action = factory(exports.Action);
+
+ exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+ };
+
+ exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+ };
+
+ exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+ };
+
+ exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+ };
+
+ exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+ };
+
+ exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+ };
+
+}).call(this);
+
+},{"./transform":7,"./util":8,"./value":9,"events":10,"heterarchy":13,"underscore":16}],4:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var assert, exports, konsole;
+
+ assert = require('./util').assert;
+
+ konsole = this;
+
+ exports = konsole;
+
+ if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+ }
+
+ if (konsole.info == null) {
+ konsole.info = konsole.log;
+ }
+
+ if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+ }
+
+ if (konsole.error == null) {
+ konsole.error = konsole.log;
+ }
+
+ if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+ }
+
+ if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+ }
+
+ if (konsole.assert == null) {
+ konsole.assert = assert;
+ }
+
+}).call(this);
+
+},{"./util":8}],5:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+ multi = require('heterarchy').multi;
+
+ ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+ behaviour = require('./behaviour');
+
+ ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+ exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+ exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+ exports.MIDI_CC = MIDI_CC = 0xB;
+
+ exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+ midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+ };
+
+ exports.midiId = midiId;
+
+ pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+ };
+
+ noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+ };
+
+ noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+ };
+
+ ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+ };
+
+ exports.pbIds = pbIds;
+
+ exports.noteOnIds = noteOnIds;
+
+ exports.noteIds = noteIds;
+
+ exports.ccIds = ccIds;
+
+ exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+ };
+
+ exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+ })(behaviour.Actor);
+
+ exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+ })(exports.Control);
+
+ exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+ })(exports.Control);
+
+ exports.input = factory(exports.InControl);
+
+ exports.output = factory(exports.OutControl);
+
+ exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+ })(multi(exports.InControl, exports.OutControl));
+
+ exports.control = factory(exports.InOutControl);
+
+}).call(this);
+
+},{"./behaviour":3,"./util":8,"heterarchy":13,"underscore":16}],6:[function(require,module,exports){
+(function (process){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+ Control = require('./control').Control;
+
+ ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+ require('./console');
+
+ basename = require('path').basename;
+
+ S = require('string');
+
+ _ = require('underscore');
+
+ exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+ };
+
+ exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+ };
+
+ exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+ };
+
+ exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+ })();
+
+}).call(this);
+
+}).call(this,require('_process'))
+},{"./console":4,"./control":5,"./util":8,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],7:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+ exports.identity = function(v) {
+ return v;
+ };
+
+ exports.identity.inverse = exports.identity;
+
+ exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+ };
+
+ exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+ };
+
+ exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+ };
+
+ exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+ };
+
+ exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+ };
+
+ exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.identityT = identityT = exports.transformI(exports.identity);
+
+ exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+ exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+ exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+ };
+
+ exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+ };
+
+ exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+ exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+ };
+
+}).call(this);
+
+},{}],8:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+ };
+
+ Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+ };
+
+ Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+ };
+
+ Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+ };
+
+ exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+ };
+
+ exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+ };
+
+ exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+ };
+
+ exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+ };
+
+ exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+ };
+
+ exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+ };
+
+ exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+ };
+
+}).call(this);
+
+},{}],9:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+ events = require('events');
+
+ util = require('./util');
+
+ factory = util.factory;
+
+ exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+ })(events.EventEmitter);
+
+ exports.value = factory(exports.Value);
+
+ exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+ })();
+
+ exports["const"] = factory(exports.Const);
+
+ exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+ })(exports.Value);
+
+ exports.reduce = factory(exports.Reduce);
+
+ exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+ })(exports.Value);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+ };
+
+}).call(this);
+
+},{"./util":8,"events":10}],10:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+function EventEmitter() {
+ this._events = this._events || {};
+ this._maxListeners = this._maxListeners || undefined;
+}
+module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+EventEmitter.EventEmitter = EventEmitter;
+
+EventEmitter.prototype._events = undefined;
+EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!isNumber(n) || n < 0 || isNaN(n))
+ throw TypeError('n must be a positive number');
+ this._maxListeners = n;
+ return this;
+};
+
+EventEmitter.prototype.emit = function(type) {
+ var er, handler, len, args, i, listeners;
+
+ if (!this._events)
+ this._events = {};
+
+ // If there is no 'error' event listener then throw.
+ if (type === 'error') {
+ if (!this._events.error ||
+ (isObject(this._events.error) && !this._events.error.length)) {
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ }
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ }
+
+ handler = this._events[type];
+
+ if (isUndefined(handler))
+ return false;
+
+ if (isFunction(handler)) {
+ switch (arguments.length) {
+ // fast cases
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ // slower
+ default:
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+
+ listeners = handler.slice();
+ len = listeners.length;
+ for (i = 0; i < len; i++)
+ listeners[i].apply(this, args);
+ }
+
+ return true;
+};
+
+EventEmitter.prototype.addListener = function(type, listener) {
+ var m;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events)
+ this._events = {};
+
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (this._events.newListener)
+ this.emit('newListener', type,
+ isFunction(listener.listener) ?
+ listener.listener : listener);
+
+ if (!this._events[type])
+ // Optimize the case of one listener. Don't need the extra array object.
+ this._events[type] = listener;
+ else if (isObject(this._events[type]))
+ // If we've already got an array, just append.
+ this._events[type].push(listener);
+ else
+ // Adding the second element, need to change to array.
+ this._events[type] = [this._events[type], listener];
+
+ // Check for listener leak
+ if (isObject(this._events[type]) && !this._events[type].warned) {
+ var m;
+ if (!isUndefined(this._maxListeners)) {
+ m = this._maxListeners;
+ } else {
+ m = EventEmitter.defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ if (typeof console.trace === 'function') {
+ // not supported in IE 10
+ console.trace();
+ }
+ }
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ var fired = false;
+
+ function g() {
+ this.removeListener(type, g);
+
+ if (!fired) {
+ fired = true;
+ listener.apply(this, arguments);
+ }
+ }
+
+ g.listener = listener;
+ this.on(type, g);
+
+ return this;
+};
+
+// emits a 'removeListener' event iff the listener was removed
+EventEmitter.prototype.removeListener = function(type, listener) {
+ var list, position, length, i;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events || !this._events[type])
+ return this;
+
+ list = this._events[type];
+ length = list.length;
+ position = -1;
+
+ if (list === listener ||
+ (isFunction(list.listener) && list.listener === listener)) {
+ delete this._events[type];
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+
+ } else if (isObject(list)) {
+ for (i = length; i-- > 0;) {
+ if (list[i] === listener ||
+ (list[i].listener && list[i].listener === listener)) {
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (list.length === 1) {
+ list.length = 0;
+ delete this._events[type];
+ } else {
+ list.splice(position, 1);
+ }
+
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ var key, listeners;
+
+ if (!this._events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!this._events.removeListener) {
+ if (arguments.length === 0)
+ this._events = {};
+ else if (this._events[type])
+ delete this._events[type];
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ for (key in this._events) {
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = {};
+ return this;
+ }
+
+ listeners = this._events[type];
+
+ if (isFunction(listeners)) {
+ this.removeListener(type, listeners);
+ } else {
+ // LIFO order
+ while (listeners.length)
+ this.removeListener(type, listeners[listeners.length - 1]);
+ }
+ delete this._events[type];
+
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ var ret;
+ if (!this._events || !this._events[type])
+ ret = [];
+ else if (isFunction(this._events[type]))
+ ret = [this._events[type]];
+ else
+ ret = this._events[type].slice();
+ return ret;
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ var ret;
+ if (!emitter._events || !emitter._events[type])
+ ret = 0;
+ else if (isFunction(emitter._events[type]))
+ ret = 1;
+ else
+ ret = emitter._events[type].length;
+ return ret;
+};
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+
+},{}],11:[function(require,module,exports){
+(function (process){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// resolves . and .. elements in a path array with directory names there
+// must be no slashes, empty elements, or device names (c:\) in the array
+// (so also no leading and trailing slashes - it does not distinguish
+// relative and absolute paths)
+function normalizeArray(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up--; up) {
+ parts.unshift('..');
+ }
+ }
+
+ return parts;
+}
+
+// Split a filename into [root, dir, basename, ext], unix version
+// 'root' is just a slash, or nothing.
+var splitPathRe =
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+var splitPath = function(filename) {
+ return splitPathRe.exec(filename).slice(1);
+};
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+};
+
+// path.normalize(path)
+// posix version
+exports.normalize = function(path) {
+ var isAbsolute = exports.isAbsolute(path),
+ trailingSlash = substr(path, -1) === '/';
+
+ // Normalize the path
+ path = normalizeArray(filter(path.split('/'), function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+
+ return (isAbsolute ? '/' : '') + path;
+};
+
+// posix version
+exports.isAbsolute = function(path) {
+ return path.charAt(0) === '/';
+};
+
+// posix version
+exports.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ if (typeof p !== 'string') {
+ throw new TypeError('Arguments to path.join must be strings');
+ }
+ return p;
+ }).join('/'));
+};
+
+
+// path.relative(from, to)
+// posix version
+exports.relative = function(from, to) {
+ from = exports.resolve(from).substr(1);
+ to = exports.resolve(to).substr(1);
+
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+
+ return outputParts.join('/');
+};
+
+exports.sep = '/';
+exports.delimiter = ':';
+
+exports.dirname = function(path) {
+ var result = splitPath(path),
+ root = result[0],
+ dir = result[1];
+
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+
+ return root + dir;
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPath(path)[2];
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPath(path)[3];
+};
+
+function filter (xs, f) {
+ if (xs.filter) return xs.filter(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (f(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// String.prototype.substr - negative index don't work in IE8
+var substr = 'ab'.substr(-1) === 'b'
+ ? function (str, start, len) { return str.substr(start, len) }
+ : function (str, start, len) {
+ if (start < 0) start = str.length + start;
+ return str.substr(start, len);
+ }
+;
+
+}).call(this,require('_process'))
+},{"_process":12}],12:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],13:[function(require,module,exports){
+// Generated by CoffeeScript 1.9.3
+(function() {
+ var assert, copyOwn, every, find, generate, head, hierarchy, inherited, isEmpty, isEqual, isJavaScriptClass, map, memoize, merge, mro, partial, ref, reject, reparent, some, tail, without,
+ slice = [].slice,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ ref = require('underscore'), head = ref.head, tail = ref.tail, map = ref.map, find = ref.find, some = ref.some, without = ref.without, isEmpty = ref.isEmpty, every = ref.every, memoize = ref.memoize, reject = ref.reject, partial = ref.partial, isEqual = ref.isEqual;
+
+ assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.multi = function() {
+ var bases;
+ bases = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return generate(merge(map(bases, mro).concat([bases])));
+ };
+
+ generate = memoize(function(linearization) {
+ var next, result;
+ next = head(linearization);
+ if (isEqual(linearization, hierarchy(next))) {
+ return next;
+ } else {
+ return result = (function(superClass) {
+ var class1;
+
+ extend(result, superClass);
+
+ function result() {
+ return class1.apply(this, arguments);
+ }
+
+ result.prototype.__mro__ = linearization;
+
+ class1 = reparent(next, result, next.prototype.constructor);
+
+ copyOwn(next, result);
+
+ copyOwn(next.prototype, result.prototype, partial(reparent, next, result));
+
+ return result;
+
+ })(generate(tail(linearization)));
+ }
+ });
+
+ copyOwn = function(from, to, project) {
+ var key, value;
+ if (project == null) {
+ project = function(x) {
+ return x;
+ };
+ }
+ for (key in from) {
+ if (!hasProp.call(from, key)) continue;
+ value = from[key];
+ if (!to.hasOwnProperty(key)) {
+ to[key] = project(value);
+ }
+ }
+ return to;
+ };
+
+ reparent = function(oldklass, newklass, value) {
+ var newsuper, oldsuper, superctor;
+ if (!(value instanceof Function)) {
+ return value;
+ } else if (value === oldklass.prototype.constructor && inherited(oldklass) === Object) {
+ superctor = inherited(newklass).prototype.constructor;
+ return function() {
+ superctor.apply(this, arguments);
+ return value.apply(this, arguments);
+ };
+ } else {
+ newsuper = inherited(newklass).prototype;
+ oldsuper = oldklass.__super__;
+ return function() {
+ oldklass.__super__ = newsuper;
+ try {
+ return value.apply(this, arguments);
+ } finally {
+ oldklass.__super__ = oldsuper;
+ }
+ };
+ }
+ };
+
+ merge = function(inputs) {
+ var next, results;
+ results = [];
+ while (!isEmpty(inputs)) {
+ next = find(map(inputs, head), function(candidate) {
+ return every(inputs, function(input) {
+ return indexOf.call(tail(input), candidate) < 0;
+ });
+ });
+ assert(next != null, "Inconsistent multiple inheritance");
+ inputs = reject(map(inputs, function(lst) {
+ return without(lst, next);
+ }), isEmpty);
+ results.push(next);
+ }
+ return results;
+ };
+
+ isJavaScriptClass = function(cls) {
+ return cls === Array || cls === Boolean || cls === Date || cls === Error || cls === Function || cls === Number || cls === RegExp || cls === String || cls === Object;
+ };
+
+ exports.mro = mro = function(cls) {
+ var result;
+ if ((cls == null) || (cls.prototype == null)) {
+ return [];
+ } else if (!cls.prototype.hasOwnProperty('__mro__')) {
+ result = [cls].concat(mro(inherited(cls)));
+ if (!isJavaScriptClass(cls)) {
+ cls.prototype.__mro__ = result;
+ }
+ return result;
+ } else {
+ return cls.prototype.__mro__;
+ }
+ };
+
+ exports.inherited = inherited = function(cls) {
+ var ref1;
+ return (ref1 = Object.getPrototypeOf(cls.prototype)) != null ? ref1.constructor : void 0;
+ };
+
+ exports.hierarchy = hierarchy = function(cls) {
+ if (cls == null) {
+ return [];
+ } else {
+ return [cls].concat(hierarchy(inherited(cls)));
+ }
+ };
+
+ exports.isinstance = function() {
+ var classes, obj;
+ obj = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.issubclass.apply(exports, [obj != null ? obj.constructor : void 0].concat(slice.call(classes)));
+ };
+
+ exports.issubclass = function() {
+ var classes, klass, linearization;
+ klass = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ linearization = mro(klass);
+ return some(classes, function(cls) {
+ return indexOf.call(linearization, cls) >= 0;
+ });
+ };
+
+}).call(this);
+
+},{"underscore":16}],14:[function(require,module,exports){
+function count(self, substr) {
+ var count = 0
+ var pos = self.indexOf(substr)
+
+ while (pos >= 0) {
+ count += 1
+ pos = self.indexOf(substr, pos + 1)
+ }
+
+ return count
+}
+
+module.exports = count
+},{}],15:[function(require,module,exports){
+/*
+string.js - Copyright (C) 2012-2014, JP Richardson
+*/
+
+!(function() {
+ "use strict";
+
+ var VERSION = '3.1.3';
+
+ var ENTITIES = {};
+
+ // from http://semplicewebsites.com/removing-accents-javascript
+ var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};
+
+//******************************************************************************
+// Added an initialize function which is essentially the code from the S
+// constructor. Now, the S constructor calls this and a new method named
+// setValue calls it as well. The setValue function allows constructors for
+// modules that extend string.js to set the initial value of an object without
+// knowing the internal workings of string.js.
+//
+// Also, all methods which return a new S object now call:
+//
+// return new this.constructor(s);
+//
+// instead of:
+//
+// return new S(s);
+//
+// This allows extended objects to keep their proper instanceOf and constructor.
+//******************************************************************************
+
+ function initialize (object, s) {
+ if (s !== null && s !== undefined) {
+ if (typeof s === 'string')
+ object.s = s;
+ else
+ object.s = s.toString();
+ } else {
+ object.s = s; //null or undefined
+ }
+
+ object.orig = s; //original object, currently only used by toCSV() and toBoolean()
+
+ if (s !== null && s !== undefined) {
+ if (object.__defineGetter__) {
+ object.__defineGetter__('length', function() {
+ return object.s.length;
+ })
+ } else {
+ object.length = s.length;
+ }
+ } else {
+ object.length = -1;
+ }
+ }
+
+ function S(s) {
+ initialize(this, s);
+ }
+
+ var __nsp = String.prototype;
+ var __sp = S.prototype = {
+
+ between: function(left, right) {
+ var s = this.s;
+ var startPos = s.indexOf(left);
+ var endPos = s.indexOf(right, startPos + left.length);
+ if (endPos == -1 && right != null)
+ return new this.constructor('')
+ else if (endPos == -1 && right == null)
+ return new this.constructor(s.substring(startPos + left.length))
+ else
+ return new this.constructor(s.slice(startPos + left.length, endPos));
+ },
+
+ //# modified slightly from https://github.com/epeli/underscore.string
+ camelize: function() {
+ var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) {
+ return (c ? c.toUpperCase() : '');
+ });
+ return new this.constructor(s);
+ },
+
+ capitalize: function() {
+ return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase());
+ },
+
+ charAt: function(index) {
+ return this.s.charAt(index);
+ },
+
+ chompLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ s = s.slice(prefix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ chompRight: function(suffix) {
+ if (this.endsWith(suffix)) {
+ var s = this.s;
+ s = s.slice(0, s.length - suffix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ //#thanks Google
+ collapseWhitespace: function() {
+ var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, '');
+ return new this.constructor(s);
+ },
+
+ contains: function(ss) {
+ return this.s.indexOf(ss) >= 0;
+ },
+
+ count: function(ss) {
+ return require('./_count')(this.s, ss)
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ dasherize: function() {
+ var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ latinise: function() {
+ var s = this.replace(/[^A-Za-z0-9\[\] ]/g, function(x) { return latin_map[x] || x; });
+ return new this.constructor(s);
+ },
+
+ decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js
+ var s = this.s;
+ s = s.replace(/(\d+);?/g, function (_, code) {
+ return String.fromCharCode(code);
+ })
+ .replace(/[xX]([A-Fa-f0-9]+);?/g, function (_, hex) {
+ return String.fromCharCode(parseInt(hex, 16));
+ })
+ .replace(/&([^;\W]+;?)/g, function (m, e) {
+ var ee = e.replace(/;$/, '');
+ var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]);
+
+ if (typeof target === 'number') {
+ return String.fromCharCode(target);
+ }
+ else if (typeof target === 'string') {
+ return target;
+ }
+ else {
+ return m;
+ }
+ })
+
+ return new this.constructor(s);
+ },
+
+ endsWith: function() {
+ var suffixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < suffixes.length; ++i) {
+ var l = this.s.length - suffixes[i].length;
+ if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true;
+ }
+ return false;
+ },
+
+ escapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
+ },
+
+ ensureLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ return this;
+ } else {
+ return new this.constructor(prefix + s);
+ }
+ },
+
+ ensureRight: function(suffix) {
+ var s = this.s;
+ if (this.endsWith(suffix)) {
+ return this;
+ } else {
+ return new this.constructor(s + suffix);
+ }
+ },
+
+ humanize: function() { //modified from underscore.string
+ if (this.s === null || this.s === undefined)
+ return new this.constructor('')
+ var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize()
+ return new this.constructor(s)
+ },
+
+ isAlpha: function() {
+ return !/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase());
+ },
+
+ isAlphaNumeric: function() {
+ return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase());
+ },
+
+ isEmpty: function() {
+ return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s);
+ },
+
+ isLower: function() {
+ return this.isAlpha() && this.s.toLowerCase() === this.s;
+ },
+
+ isNumeric: function() {
+ return !/[^0-9]/.test(this.s);
+ },
+
+ isUpper: function() {
+ return this.isAlpha() && this.s.toUpperCase() === this.s;
+ },
+
+ left: function(N) {
+ if (N >= 0) {
+ var s = this.s.substr(0, N);
+ return new this.constructor(s);
+ } else {
+ return this.right(-N);
+ }
+ },
+
+ lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines
+ return this.replaceAll('\r\n', '\n').s.split('\n');
+ },
+
+ pad: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ len = len - this.s.length;
+ var left = Array(Math.ceil(len / 2) + 1).join(ch);
+ var right = Array(Math.floor(len / 2) + 1).join(ch);
+ return new this.constructor(left + this.s + right);
+ },
+
+ padLeft: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s);
+ },
+
+ padRight: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch));
+ },
+
+ parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what
+ delimiter = delimiter || ',';
+ escape = escape || '\\'
+ if (typeof qualifier == 'undefined')
+ qualifier = '"';
+
+ var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this;
+ var ca = function(i){return self.s.charAt(i)};
+ if (typeof lineDelimiter !== 'undefined') var rows = [];
+
+ if (!qualifier)
+ inField = true;
+
+ while (i < len) {
+ var current = ca(i);
+ switch (current) {
+ case escape:
+ //fix for issues #32 and #35
+ if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) {
+ i += 1;
+ fieldBuffer.push(ca(i));
+ break;
+ }
+ if (escape !== qualifier) break;
+ case qualifier:
+ inField = !inField;
+ break;
+ case delimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ }
+ if (inField && qualifier)
+ fieldBuffer.push(current);
+ else {
+ fields.push(fieldBuffer.join(''))
+ fieldBuffer.length = 0;
+ }
+ break;
+ case lineDelimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ else if (inField) {
+ fieldBuffer.push(current);
+ } else {
+ if (rows) {
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ }
+ break;
+ case ' ':
+ if (inField)
+ fieldBuffer.push(current);
+ break;
+ default:
+ if (inField)
+ fieldBuffer.push(current);
+ else if(current!==qualifier) {
+ fieldBuffer.push(current);
+ inField=true;
+ inUnqualifiedString=true;
+ }
+ break;
+ }
+ i += 1;
+ }
+
+ fields.push(fieldBuffer.join(''));
+ if (rows) {
+ rows.push(fields);
+ return rows;
+ }
+ return fields;
+ },
+
+ replaceAll: function(ss, r) {
+ //var s = this.s.replace(new RegExp(ss, 'g'), r);
+ var s = this.s.split(ss).join(r)
+ return new this.constructor(s);
+ },
+
+ strip: function() {
+ var ss = this.s;
+ for(var i= 0, n=arguments.length; i= 0) {
+ var s = this.s.substr(this.s.length - N, N);
+ return new this.constructor(s);
+ } else {
+ return this.left(-N);
+ }
+ },
+
+ setValue: function (s) {
+ initialize(this, s);
+ return this;
+ },
+
+ slugify: function() {
+ var sl = (new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s;
+ if (sl.charAt(0) === '-')
+ sl = sl.substr(1);
+ return new this.constructor(sl);
+ },
+
+ startsWith: function() {
+ var prefixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < prefixes.length; ++i) {
+ if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true;
+ }
+ return false;
+ },
+
+ stripPunctuation: function() {
+ //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
+ return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
+ },
+
+ stripTags: function() { //from sugar.js
+ var s = this.s, args = arguments.length > 0 ? arguments : [''];
+ multiArgs(args, function(tag) {
+ s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), '');
+ });
+ return new this.constructor(s);
+ },
+
+ template: function(values, opening, closing) {
+ var s = this.s
+ var opening = opening || Export.TMPL_OPEN
+ var closing = closing || Export.TMPL_CLOSE
+
+ var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var r = new RegExp(open + '(.+?)' + close, 'g')
+ //, r = /\{\{(.+?)\}\}/g
+ var matches = s.match(r) || [];
+
+ matches.forEach(function(match) {
+ var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }}
+ var value = typeof values[key] == 'undefined' ? '' : values[key];
+ s = s.replace(match, value);
+ });
+ return new this.constructor(s);
+ },
+
+ times: function(n) {
+ return new this.constructor(new Array(n + 1).join(this.s));
+ },
+
+ toBoolean: function() {
+ if (typeof this.orig === 'string') {
+ var s = this.s.toLowerCase();
+ return s === 'true' || s === 'yes' || s === 'on' || s === '1';
+ } else
+ return this.orig === true || this.orig === 1;
+ },
+
+ toFloat: function(precision) {
+ var num = parseFloat(this.s)
+ if (precision)
+ return parseFloat(num.toFixed(precision))
+ else
+ return num
+ },
+
+ toInt: function() { //thanks Google
+ // If the string starts with '0x' or '-0x', parse as hex.
+ return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10)
+ },
+
+ trim: function() {
+ var s;
+ if (typeof __nsp.trim === 'undefined')
+ s = this.s.replace(/(^\s*|\s*$)/g, '')
+ else
+ s = this.s.trim()
+ return new this.constructor(s);
+ },
+
+ trimLeft: function() {
+ var s;
+ if (__nsp.trimLeft)
+ s = this.s.trimLeft();
+ else
+ s = this.s.replace(/(^\s*)/g, '');
+ return new this.constructor(s);
+ },
+
+ trimRight: function() {
+ var s;
+ if (__nsp.trimRight)
+ s = this.s.trimRight();
+ else
+ s = this.s.replace(/\s+$/, '');
+ return new this.constructor(s);
+ },
+
+ truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz
+ var str = this.s;
+
+ length = ~~length;
+ pruneStr = pruneStr || '...';
+
+ if (str.length <= length) return new this.constructor(str);
+
+ var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
+ template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
+
+ if (template.slice(template.length-2).match(/\w\w/))
+ template = template.replace(/\s*\S+$/, '');
+ else
+ template = new S(template.slice(0, template.length-1)).trimRight().s;
+
+ return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr);
+ },
+
+ toCSV: function() {
+ var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false;
+ var dataArray = [];
+
+ function hasVal(it) {
+ return it !== null && it !== '';
+ }
+
+ if (typeof arguments[0] === 'object') {
+ delim = arguments[0].delimiter || delim;
+ delim = arguments[0].separator || delim;
+ qualifier = arguments[0].qualifier || qualifier;
+ encloseNumbers = !!arguments[0].encloseNumbers;
+ escape = arguments[0].escape || escape;
+ keys = !!arguments[0].keys;
+ } else if (typeof arguments[0] === 'string') {
+ delim = arguments[0];
+ }
+
+ if (typeof arguments[1] === 'string')
+ qualifier = arguments[1];
+
+ if (arguments[1] === null)
+ qualifier = null;
+
+ if (this.orig instanceof Array)
+ dataArray = this.orig;
+ else { //object
+ for (var key in this.orig)
+ if (this.orig.hasOwnProperty(key))
+ if (keys)
+ dataArray.push(key);
+ else
+ dataArray.push(this.orig[key]);
+ }
+
+ var rep = escape + qualifier;
+ var buildString = [];
+ for (var i = 0; i < dataArray.length; ++i) {
+ var shouldQualify = hasVal(qualifier)
+ if (typeof dataArray[i] == 'number')
+ shouldQualify &= encloseNumbers;
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (dataArray[i] !== null && dataArray[i] !== undefined) {
+ var d = new S(dataArray[i]).replaceAll(qualifier, rep).s;
+ buildString.push(d);
+ } else
+ buildString.push('')
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (delim)
+ buildString.push(delim);
+ }
+
+ //chop last delim
+ //console.log(buildString.length)
+ buildString.length = buildString.length - 1;
+ return new this.constructor(buildString.join(''));
+ },
+
+ toString: function() {
+ return this.s;
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ underscore: function() {
+ var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/([A-Z\d]+)([A-Z][a-z])/,'$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ unescapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){
+ var match;
+
+ if (entityCode in escapeChars) {
+ return escapeChars[entityCode];
+ } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
+ return String.fromCharCode(parseInt(match[1], 16));
+ } else if (match = entityCode.match(/^#(\d+)$/)) {
+ return String.fromCharCode(~~match[1]);
+ } else {
+ return entity;
+ }
+ }));
+ },
+
+ valueOf: function() {
+ return this.s.valueOf();
+ },
+
+ //#Added a New Function called wrapHTML.
+ wrapHTML: function (tagName, tagAttrs) {
+ var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = '';
+ if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"';
+ s = wrapped.concat('<', el, elAttr, '>', this, '', el, '>');
+ return new this.constructor(s);
+ }
+ }
+
+ var methodsAdded = [];
+ function extendPrototype() {
+ for (var name in __sp) {
+ (function(name){
+ var func = __sp[name];
+ if (!__nsp.hasOwnProperty(name)) {
+ methodsAdded.push(name);
+ __nsp[name] = function() {
+ String.prototype.s = this;
+ return func.apply(this, arguments);
+ }
+ }
+ })(name);
+ }
+ }
+
+ function restorePrototype() {
+ for (var i = 0; i < methodsAdded.length; ++i)
+ delete String.prototype[methodsAdded[i]];
+ methodsAdded.length = 0;
+ }
+
+
+/*************************************
+/* Attach Native JavaScript String Properties
+/*************************************/
+
+ var nativeProperties = getNativeStringProperties();
+ for (var name in nativeProperties) {
+ (function(name) {
+ var stringProp = __nsp[name];
+ if (typeof stringProp == 'function') {
+ //console.log(stringProp)
+ if (!__sp[name]) {
+ if (nativeProperties[name] === 'string') {
+ __sp[name] = function() {
+ //console.log(name)
+ return new this.constructor(stringProp.apply(this, arguments));
+ }
+ } else {
+ __sp[name] = stringProp;
+ }
+ }
+ }
+ })(name);
+ }
+
+
+/*************************************
+/* Function Aliases
+/*************************************/
+
+ __sp.repeat = __sp.times;
+ __sp.include = __sp.contains;
+ __sp.toInteger = __sp.toInt;
+ __sp.toBool = __sp.toBoolean;
+ __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML'
+
+
+//******************************************************************************
+// Set the constructor. Without this, string.js objects are instances of
+// Object instead of S.
+//******************************************************************************
+
+ __sp.constructor = S;
+
+
+/*************************************
+/* Private Functions
+/*************************************/
+
+ function getNativeStringProperties() {
+ var names = getNativeStringPropertyNames();
+ var retObj = {};
+
+ for (var i = 0; i < names.length; ++i) {
+ var name = names[i];
+ var func = __nsp[name];
+ try {
+ // #127: pass extra parameter to keep shelljs happy
+ var type = typeof func.apply('test', ['string']);
+ retObj[name] = type;
+ } catch (e) {}
+ }
+ return retObj;
+ }
+
+ function getNativeStringPropertyNames() {
+ var results = [];
+ if (Object.getOwnPropertyNames) {
+ results = Object.getOwnPropertyNames(__nsp);
+ results.splice(results.indexOf('valueOf'), 1);
+ results.splice(results.indexOf('toString'), 1);
+ return results;
+ } else { //meant for legacy cruft, this could probably be made more efficient
+ var stringNames = {};
+ var objectNames = [];
+ for (var name in String.prototype)
+ stringNames[name] = name;
+
+ for (var name in Object.prototype)
+ delete stringNames[name];
+
+ //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names
+ for (var name in stringNames) {
+ results.push(name);
+ }
+ return results;
+ }
+ }
+
+ function Export(str) {
+ return new S(str);
+ };
+
+ //attach exports to StringJSWrapper
+ Export.extendPrototype = extendPrototype;
+ Export.restorePrototype = restorePrototype;
+ Export.VERSION = VERSION;
+ Export.TMPL_OPEN = '{{';
+ Export.TMPL_CLOSE = '}}';
+ Export.ENTITIES = ENTITIES;
+
+
+
+/*************************************
+/* Exports
+/*************************************/
+
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
+ module.exports = Export;
+
+ } else {
+
+ if(typeof define === "function" && define.amd) {
+ define([], function() {
+ return Export;
+ });
+ } else {
+ window.S = Export;
+ }
+ }
+
+
+/*************************************
+/* 3rd Party Private Functions
+/*************************************/
+
+ //from sugar.js
+ function multiArgs(args, fn) {
+ var result = [], i;
+ for(i = 0; i < args.length; i++) {
+ result.push(args[i]);
+ if(fn) fn.call(args, args[i], i);
+ }
+ return result;
+ }
+
+ //from underscore.string
+ var escapeChars = {
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ apos: "'",
+ amp: '&'
+ };
+
+ function escapeRegExp (s) {
+ // most part from https://github.com/skulpt/skulpt/blob/ecaf75e69c2e539eff124b2ab45df0b01eaf2295/src/str.js#L242
+ var c;
+ var i;
+ var ret = [];
+ var re = /^[A-Za-z0-9]+$/;
+ s = ensureString(s);
+ for (i = 0; i < s.length; ++i) {
+ c = s.charAt(i);
+
+ if (re.test(c)) {
+ ret.push(c);
+ }
+ else {
+ if (c === "\\000") {
+ ret.push("\\000");
+ }
+ else {
+ ret.push("\\" + c);
+ }
+ }
+ }
+ return ret.join("");
+ }
+
+ function ensureString(string) {
+ return string == null ? '' : '' + string;
+ }
+
+ //from underscore.string
+ var reversedEscapeChars = {};
+ for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
+
+ ENTITIES = {
+ "amp" : "&",
+ "gt" : ">",
+ "lt" : "<",
+ "quot" : "\"",
+ "apos" : "'",
+ "AElig" : 198,
+ "Aacute" : 193,
+ "Acirc" : 194,
+ "Agrave" : 192,
+ "Aring" : 197,
+ "Atilde" : 195,
+ "Auml" : 196,
+ "Ccedil" : 199,
+ "ETH" : 208,
+ "Eacute" : 201,
+ "Ecirc" : 202,
+ "Egrave" : 200,
+ "Euml" : 203,
+ "Iacute" : 205,
+ "Icirc" : 206,
+ "Igrave" : 204,
+ "Iuml" : 207,
+ "Ntilde" : 209,
+ "Oacute" : 211,
+ "Ocirc" : 212,
+ "Ograve" : 210,
+ "Oslash" : 216,
+ "Otilde" : 213,
+ "Ouml" : 214,
+ "THORN" : 222,
+ "Uacute" : 218,
+ "Ucirc" : 219,
+ "Ugrave" : 217,
+ "Uuml" : 220,
+ "Yacute" : 221,
+ "aacute" : 225,
+ "acirc" : 226,
+ "aelig" : 230,
+ "agrave" : 224,
+ "aring" : 229,
+ "atilde" : 227,
+ "auml" : 228,
+ "ccedil" : 231,
+ "eacute" : 233,
+ "ecirc" : 234,
+ "egrave" : 232,
+ "eth" : 240,
+ "euml" : 235,
+ "iacute" : 237,
+ "icirc" : 238,
+ "igrave" : 236,
+ "iuml" : 239,
+ "ntilde" : 241,
+ "oacute" : 243,
+ "ocirc" : 244,
+ "ograve" : 242,
+ "oslash" : 248,
+ "otilde" : 245,
+ "ouml" : 246,
+ "szlig" : 223,
+ "thorn" : 254,
+ "uacute" : 250,
+ "ucirc" : 251,
+ "ugrave" : 249,
+ "uuml" : 252,
+ "yacute" : 253,
+ "yuml" : 255,
+ "copy" : 169,
+ "reg" : 174,
+ "nbsp" : 160,
+ "iexcl" : 161,
+ "cent" : 162,
+ "pound" : 163,
+ "curren" : 164,
+ "yen" : 165,
+ "brvbar" : 166,
+ "sect" : 167,
+ "uml" : 168,
+ "ordf" : 170,
+ "laquo" : 171,
+ "not" : 172,
+ "shy" : 173,
+ "macr" : 175,
+ "deg" : 176,
+ "plusmn" : 177,
+ "sup1" : 185,
+ "sup2" : 178,
+ "sup3" : 179,
+ "acute" : 180,
+ "micro" : 181,
+ "para" : 182,
+ "middot" : 183,
+ "cedil" : 184,
+ "ordm" : 186,
+ "raquo" : 187,
+ "frac14" : 188,
+ "frac12" : 189,
+ "frac34" : 190,
+ "iquest" : 191,
+ "times" : 215,
+ "divide" : 247,
+ "OElig;" : 338,
+ "oelig;" : 339,
+ "Scaron;" : 352,
+ "scaron;" : 353,
+ "Yuml;" : 376,
+ "fnof;" : 402,
+ "circ;" : 710,
+ "tilde;" : 732,
+ "Alpha;" : 913,
+ "Beta;" : 914,
+ "Gamma;" : 915,
+ "Delta;" : 916,
+ "Epsilon;" : 917,
+ "Zeta;" : 918,
+ "Eta;" : 919,
+ "Theta;" : 920,
+ "Iota;" : 921,
+ "Kappa;" : 922,
+ "Lambda;" : 923,
+ "Mu;" : 924,
+ "Nu;" : 925,
+ "Xi;" : 926,
+ "Omicron;" : 927,
+ "Pi;" : 928,
+ "Rho;" : 929,
+ "Sigma;" : 931,
+ "Tau;" : 932,
+ "Upsilon;" : 933,
+ "Phi;" : 934,
+ "Chi;" : 935,
+ "Psi;" : 936,
+ "Omega;" : 937,
+ "alpha;" : 945,
+ "beta;" : 946,
+ "gamma;" : 947,
+ "delta;" : 948,
+ "epsilon;" : 949,
+ "zeta;" : 950,
+ "eta;" : 951,
+ "theta;" : 952,
+ "iota;" : 953,
+ "kappa;" : 954,
+ "lambda;" : 955,
+ "mu;" : 956,
+ "nu;" : 957,
+ "xi;" : 958,
+ "omicron;" : 959,
+ "pi;" : 960,
+ "rho;" : 961,
+ "sigmaf;" : 962,
+ "sigma;" : 963,
+ "tau;" : 964,
+ "upsilon;" : 965,
+ "phi;" : 966,
+ "chi;" : 967,
+ "psi;" : 968,
+ "omega;" : 969,
+ "thetasym;" : 977,
+ "upsih;" : 978,
+ "piv;" : 982,
+ "ensp;" : 8194,
+ "emsp;" : 8195,
+ "thinsp;" : 8201,
+ "zwnj;" : 8204,
+ "zwj;" : 8205,
+ "lrm;" : 8206,
+ "rlm;" : 8207,
+ "ndash;" : 8211,
+ "mdash;" : 8212,
+ "lsquo;" : 8216,
+ "rsquo;" : 8217,
+ "sbquo;" : 8218,
+ "ldquo;" : 8220,
+ "rdquo;" : 8221,
+ "bdquo;" : 8222,
+ "dagger;" : 8224,
+ "Dagger;" : 8225,
+ "bull;" : 8226,
+ "hellip;" : 8230,
+ "permil;" : 8240,
+ "prime;" : 8242,
+ "Prime;" : 8243,
+ "lsaquo;" : 8249,
+ "rsaquo;" : 8250,
+ "oline;" : 8254,
+ "frasl;" : 8260,
+ "euro;" : 8364,
+ "image;" : 8465,
+ "weierp;" : 8472,
+ "real;" : 8476,
+ "trade;" : 8482,
+ "alefsym;" : 8501,
+ "larr;" : 8592,
+ "uarr;" : 8593,
+ "rarr;" : 8594,
+ "darr;" : 8595,
+ "harr;" : 8596,
+ "crarr;" : 8629,
+ "lArr;" : 8656,
+ "uArr;" : 8657,
+ "rArr;" : 8658,
+ "dArr;" : 8659,
+ "hArr;" : 8660,
+ "forall;" : 8704,
+ "part;" : 8706,
+ "exist;" : 8707,
+ "empty;" : 8709,
+ "nabla;" : 8711,
+ "isin;" : 8712,
+ "notin;" : 8713,
+ "ni;" : 8715,
+ "prod;" : 8719,
+ "sum;" : 8721,
+ "minus;" : 8722,
+ "lowast;" : 8727,
+ "radic;" : 8730,
+ "prop;" : 8733,
+ "infin;" : 8734,
+ "ang;" : 8736,
+ "and;" : 8743,
+ "or;" : 8744,
+ "cap;" : 8745,
+ "cup;" : 8746,
+ "int;" : 8747,
+ "there4;" : 8756,
+ "sim;" : 8764,
+ "cong;" : 8773,
+ "asymp;" : 8776,
+ "ne;" : 8800,
+ "equiv;" : 8801,
+ "le;" : 8804,
+ "ge;" : 8805,
+ "sub;" : 8834,
+ "sup;" : 8835,
+ "nsub;" : 8836,
+ "sube;" : 8838,
+ "supe;" : 8839,
+ "oplus;" : 8853,
+ "otimes;" : 8855,
+ "perp;" : 8869,
+ "sdot;" : 8901,
+ "lceil;" : 8968,
+ "rceil;" : 8969,
+ "lfloor;" : 8970,
+ "rfloor;" : 8971,
+ "lang;" : 9001,
+ "rang;" : 9002,
+ "loz;" : 9674,
+ "spades;" : 9824,
+ "clubs;" : 9827,
+ "hearts;" : 9829,
+ "diams;" : 9830
+ }
+
+
+}).call(this);
+
+},{"./_count":14}],16:[function(require,module,exports){
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
+
+},{}],"/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco":[function(require,module,exports){
+var assert, b, c, mixco, v;
+
+mixco = require('mixco');
+
+assert = mixco.util.assert;
+
+c = mixco.control;
+
+b = mixco.behaviour;
+
+v = mixco.value;
+
+mixco.script.register(module, {
+ info: {
+ name: '[mixco] M-Audio Xponent',
+ author: 'Juan Pedro Bolivar Puente ',
+ wiki: 'https://sinusoid.es/mixco/script/maudio_xponent.mixco.html',
+ forums: 'https://github.com/arximboldi/mixco/issues',
+ description: "Controller mapping for the M-Audio Xponent DJ controller."
+ },
+ constructor: function() {
+ var ccId, g;
+ ccId = function(cc) {
+ return c.ccIds(cc, 2);
+ };
+ g = "[Master]";
+ c.input(ccId(0x0D)).does(g, "headMix");
+ c.input(ccId(0x07)).does(g, "crossfader");
+ c.input(0x0c, 0x00).does(b.soft("[EffectRack1_EffectUnit1]", "super1"));
+ c.input(0x0d, 0x00).does(b.soft("[EffectRack1_EffectUnit1]", "mix"));
+ c.input(0x0c, 0x01).does(b.soft("[EffectRack1_EffectUnit2]", "super1"));
+ c.input(0x0d, 0x01).does(b.soft("[EffectRack1_EffectUnit2]", "mix"));
+ c.control(0x09, 0x02).does("[EffectRack1_EffectUnit1_Effect1]", "parameter1");
+ c.control(0x08, 0x02).does("[EffectRack1_EffectUnit1_Effect1]", "parameter2");
+ c.input(c.noteOnIds(0x00, 0x02)).does("[EffectRack1_EffectUnit1]", "group_[Channel1]_enable");
+ c.input(c.noteOnIds(0x01, 0x02)).does("[EffectRack1_EffectUnit1]", "group_[Channel2]_enable");
+ this.decks = b.chooser();
+ this.addDeck(0);
+ return this.addDeck(1);
+ },
+ addDeck: function(i) {
+ var beatloop, ccId, g, idx, j, noteId, noteOnId, scratchMode, selectTrackKnobTransform, shift;
+ assert(i === 0 || i === 1);
+ g = "[Channel" + (i + 1) + "]";
+ ccId = function(cc) {
+ return c.ccIds(cc, i);
+ };
+ noteId = function(note) {
+ return c.noteIds(note, i);
+ };
+ noteOnId = function(note) {
+ return c.noteOnIds(note, i);
+ };
+ shift = b.modifier();
+ c.control(noteId(0x2C)).does(shift);
+ c.control(noteOnId(0x14)).does(this.decks.add(g, "pfl"));
+ c.control(noteId(0x08)).does(g, "filterLowKill");
+ c.control(noteId(0x09)).does(g, "filterMidKill");
+ c.control(noteId(0x0A)).does(g, "filterHighKill");
+ c.control(noteId(0x0B)).does(g, "pregain_toggle");
+ c.input(ccId(0x08)).does(g, "filterLow");
+ c.input(ccId(0x09)).does(g, "filterMid");
+ c.input(ccId(0x0A)).does(g, "filterHigh");
+ c.input(ccId(0x0B)).does(b.soft(g, "pregain"));
+ c.output(c.ccIds(0x12 + i, 3)).does(b.mapOut(g, "VuMeter").meter());
+ c.control(noteId(0x02)).does(g, "sync_enabled");
+ c.input(ccId(0x07)).does(b.soft(g, "volume"));
+ c.control(noteId(0x07)).does(b.punchIn(0.5 - i));
+ c.output(c.ccIds(0x14 + i, 3)).does(b.playhead(g));
+ c.control(noteId(0x21)).does(g, "back");
+ c.control(noteId(0x22)).does(g, "fwd");
+ for (idx = j = 0; j <= 4; idx = ++j) {
+ c.control(noteId(0x17 + idx)).when(shift, g, "hotcue_" + (idx + 1) + "_clear", g, "hotcue_" + (idx + 1) + "_enabled")["else"](g, "hotcue_" + (idx + 1) + "_activate", g, "hotcue_" + (idx + 1) + "_enabled");
+ }
+ c.control(noteId(0x1C)).when(shift, g, "beatjump_1_backward")["else"](g, "beatjump_4_backward");
+ c.control(noteId(0x1D)).when(shift, g, "beatjump_1_forward")["else"](g, "beatjump_4_forward");
+ c.control(noteId(0x1E)).when(shift, "[Playlist]", "ToggleSelectedSidebarItem")["else"](g, "keylock");
+ c.control(noteId(0x1F)).does(g, "beats_translate_curpos");
+ c.control(noteId(0x20)).does(g, "reverse");
+ c.control(noteId(0x23)).does(g, "cue_default", g, "cue_indicator");
+ c.control(noteOnId(0x24)).does(g, "play");
+ c.control(noteId(0x29)).when(shift, g, "loop_halve")["else"](g, "loop_in");
+ c.control(noteId(0x2B)).when(shift, g, "loop_double")["else"](g, "loop_out");
+ c.control(noteOnId(0x2A)).does(g, "reloop_exit", g, "loop_enabled");
+ c.control(noteId(0x25)).when(shift, g, "beatloop_0.125_activate", g, "beatloop_0.125_enabled")["else"](g, "beatloop_4_activate", g, "beatloop_4_enabled");
+ c.control(noteId(0x26)).when(shift, g, "beatloop_0.5_activate", g, "beatloop_0.5_enabled")["else"](g, "beatloop_8_activate", g, "beatloop_8_enabled");
+ c.control(noteId(0x27)).when(shift, g, "beatloop_1_activate", g, "beatloop_1_enabled")["else"](g, "beatloop_16_activate", g, "beatloop_16_enabled");
+ c.control(noteId(0x28)).when(shift, g, "beatloop_2_activate", g, "beatloop_2_enabled")["else"](g, "beatloop_32_activate", g, "beatloop_32_enabled");
+ c.control(noteOnId(0x0c)).does("[EffectRack1_EffectUnit1]", "group_" + g + "_enable");
+ c.control(noteOnId(0x0d)).does("[EffectRack1_EffectUnit2]", "group_" + g + "_enable");
+ beatloop = b.beatEffect(g, 'roll');
+ c.input(ccId(0x0e)).does(beatloop.selector());
+ c.control(noteId(0x0e)).does(beatloop);
+ c.input(ccId(0x0f)).does("[QuickEffectRack1_" + g + "]", 'super1');
+ c.control(noteId(0x0f)).does("[QuickEffectRack1_" + g + "]", 'enabled');
+ scratchMode = b["switch"]();
+ c.control(noteOnId(0x15)).does(scratchMode);
+ selectTrackKnobTransform = (function() {
+ var toggle;
+ toggle = 1;
+ return function(ev) {
+ var val;
+ val = ev.value - 64;
+ toggle -= 1;
+ if (toggle < 0) {
+ toggle = 3;
+ }
+ if (toggle === 0) {
+ return val.sign();
+ } else {
+ return null;
+ }
+ };
+ })();
+ c.control(noteId(0x16)).when(v.and(v.not(shift), scratchMode), b.scratchEnable(i + 1));
+ c.input(ccId(0x16)).when(shift, b.map("[Playlist]", "SelectTrackKnob").transform(selectTrackKnobTransform))["else"].when(scratchMode, b.scratchTick(i + 1).options.spread64)["else"](b.map(g, "jog").transform(function(ev) {
+ return (ev.value - 64) / 8;
+ }));
+ c.control(noteId(0x10)).when(shift, g, "rate_temp_down_small")["else"](g, "rate_temp_down");
+ c.control(noteId(0x11)).when(shift, g, "rate_temp_up_small")["else"](g, "rate_temp_up");
+ c.input(c.pbIds(i)).does(b.soft(g, "rate"));
+ c.control(noteId(0x12)).when(shift, g, "eject")["else"](b.brake(i + 1));
+ return c.control(noteId(0x13)).when(shift, g, "LoadSelectedTrack")["else"](b.spinback(i + 1));
+ },
+ preinit: function() {
+ var msg;
+ msg = [0xF0, 0x00, 0x20, 0x08, 0x00, 0x00, 0x63, 0x0E, 0x16, 0x40, 0x00, 0x01, 0xF7];
+ return this.mixxx.midi.sendSysexMsg(msg, msg.length);
+ },
+ init: function() {
+ return this.decks.activate(0);
+ },
+ postshutdown: function() {
+ var msg;
+ msg = [0xF0, 0x00, 0x20, 0x08, 0x00, 0x00, 0x63, 0x0E, 0x16, 0x40, 0x00, 0x00, 0xF7];
+ return this.mixxx.midi.sendSysexMsg(msg, msg.length);
+ }
+});
+
+
+},{"mixco":2}],17:[function(require,module,exports){
+var _, assert, bind, copy, events, extend, factory, indent, isinstance, makeOptionsChooser, map, multi, option, ref, ref1, ref2, toOption, transform, value,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+transform = require('./transform');
+
+value = require('./value');
+
+ref = require('./util'), indent = ref.indent, assert = ref.assert, factory = ref.factory, copy = ref.copy;
+
+ref1 = require('heterarchy'), multi = ref1.multi, isinstance = ref1.isinstance;
+
+_ = (ref2 = require('underscore'), extend = ref2.extend, bind = ref2.bind, map = ref2.map, ref2);
+
+exports.Actor = (function(superClass) {
+ extend1(Actor, superClass);
+
+ function Actor() {
+ return Actor.__super__.constructor.apply(this, arguments);
+ }
+
+ Actor.prototype.send = void 0;
+
+ return Actor;
+
+})(events.EventEmitter);
+
+toOption = function(option) {
+ var result;
+ result = option;
+ if (isinstance(option, Function)) {
+ result = {
+ transform: option
+ };
+ }
+ if ((result.transform != null) && (result.process == null)) {
+ result.process = result.transform.length === 1 ? function(ev, b) {
+ return ev.value = this.transform(ev.value);
+ } : function(ev, b) {
+ return ev.value = this.transform(ev.value, b.midiValue);
+ };
+ }
+ return result;
+};
+
+option = exports.option = (function() {
+ var add, result, rot64;
+ result = {};
+ add = function() {
+ var desc, i, mixxxName, name, names, option;
+ names = 2 <= arguments.length ? slice.call(arguments, 0, i = arguments.length - 1) : (i = 0, []), option = arguments[i++];
+ mixxxName = names[0], name = names[1];
+ desc = toOption(option);
+ desc.name = mixxxName;
+ result[name != null ? name : mixxxName] = desc;
+ return result;
+ };
+ rot64 = function(sign) {
+ return function(v1, v0) {
+ var diff;
+ diff = v1 - (64..diff = diff === -1 || diff === 1 ? diff / 16.0 : diff - diff.sign());
+ return (v0 + diff * sign).clamp(0, 127);
+ };
+ };
+ add('invert', function(v) {
+ return 127.0 - v;
+ });
+ add('rot64', rot64(1));
+ add('rot64inv', rot64(-1));
+ add('rot64fast', function(v1, v0) {
+ return (v0 + (v1 - 64) * 1.5).clamp(0, 127);
+ });
+ add('diff', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+})();
+
+exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+};
+
+exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+})(value.Value);
+
+exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+})(exports.Behaviour);
+
+exports.call = factory(exports.Call);
+
+exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+})(exports.Behaviour);
+
+exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+})(exports.Output);
+
+exports.transform = factory(exports.Transform);
+
+exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+};
+
+exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+};
+
+exports.switch_ = exports["switch"];
+
+exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+})(exports.Behaviour);
+
+exports.mapIn = factory(exports.MapIn);
+
+exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+})(exports.Output);
+
+exports.mapOut = factory(exports.MapOut);
+
+exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+})(multi(exports.MapIn, exports.MapOut));
+
+exports.map = factory(exports.Map);
+
+exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+};
+
+exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+};
+
+exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+};
+
+exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+};
+
+exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+})(exports.Output);
+
+exports.chooser = factory(exports.Chooser);
+
+exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+})(exports.Behaviour);
+
+exports.when = factory(exports.When);
+
+exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+})(exports.Output);
+
+exports.action = factory(exports.Action);
+
+exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+};
+
+exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+};
+
+exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+};
+
+exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+};
+
+exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+};
+
+exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+};
+
+
+},{"./transform":21,"./util":22,"./value":23,"events":10,"heterarchy":13,"underscore":16}],18:[function(require,module,exports){
+var assert, exports, konsole;
+
+assert = require('./util').assert;
+
+konsole = this;
+
+exports = konsole;
+
+if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+}
+
+if (konsole.info == null) {
+ konsole.info = konsole.log;
+}
+
+if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+}
+
+if (konsole.error == null) {
+ konsole.error = konsole.log;
+}
+
+if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+}
+
+if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+}
+
+if (konsole.assert == null) {
+ konsole.assert = assert;
+}
+
+
+},{"./util":22}],19:[function(require,module,exports){
+var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+multi = require('heterarchy').multi;
+
+ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+behaviour = require('./behaviour');
+
+ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+exports.MIDI_CC = MIDI_CC = 0xB;
+
+exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+};
+
+exports.midiId = midiId;
+
+pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+};
+
+noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+};
+
+noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+};
+
+ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+};
+
+exports.pbIds = pbIds;
+
+exports.noteOnIds = noteOnIds;
+
+exports.noteIds = noteIds;
+
+exports.ccIds = ccIds;
+
+exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+};
+
+exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+})(behaviour.Actor);
+
+exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+})(exports.Control);
+
+exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+})(exports.Control);
+
+exports.input = factory(exports.InControl);
+
+exports.output = factory(exports.OutControl);
+
+exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+})(multi(exports.InControl, exports.OutControl));
+
+exports.control = factory(exports.InOutControl);
+
+
+},{"./behaviour":17,"./util":22,"heterarchy":13,"underscore":16}],20:[function(require,module,exports){
+(function (process){
+var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+Control = require('./control').Control;
+
+ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+require('./console');
+
+basename = require('path').basename;
+
+S = require('string');
+
+_ = require('underscore');
+
+exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+};
+
+exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+};
+
+exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+};
+
+exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+})();
+
+
+}).call(this,require('_process'))
+},{"./console":18,"./control":19,"./util":22,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],21:[function(require,module,exports){
+var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+exports.identity = function(v) {
+ return v;
+};
+
+exports.identity.inverse = exports.identity;
+
+exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+};
+
+exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+};
+
+exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+};
+
+exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+};
+
+exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+};
+
+exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.identityT = identityT = exports.transformI(exports.identity);
+
+exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+};
+
+exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+};
+
+exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+};
+
+
+},{}],22:[function(require,module,exports){
+Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+};
+
+Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+};
+
+Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+};
+
+Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+};
+
+exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+};
+
+exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+};
+
+exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+};
+
+exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+};
+
+exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+};
+
+exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+};
+
+exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+};
+
+exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+};
+
+exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+};
+
+
+},{}],23:[function(require,module,exports){
+var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+util = require('./util');
+
+factory = util.factory;
+
+exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+})(events.EventEmitter);
+
+exports.value = factory(exports.Value);
+
+exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+})();
+
+exports["const"] = factory(exports.Const);
+
+exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+})(exports.Value);
+
+exports.reduce = factory(exports.Reduce);
+
+exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+})(exports.Value);
+
+exports.transform = factory(exports.Transform);
+
+exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+};
+
+
+},{"./util":22,"events":10}]},{},[1]);
+
+maudio_xponent = require('/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco').maudio_xponent;
+/* End of Mixco generated script */
\ No newline at end of file
diff --git a/res/controllers/maudio_xponent.mixco.output.midi.xml b/res/controllers/maudio_xponent.mixco.output.midi.xml
new file mode 100644
index 000000000000..ea69ef9bfe94
--- /dev/null
+++ b/res/controllers/maudio_xponent.mixco.output.midi.xml
@@ -0,0 +1,1874 @@
+
+
+
+ M-Audio Xponent
+ Juan Pedro Bolivar Puente <raskolnikov@gnu.org>
+ Controller mapping for the M-Audio Xponent DJ controller.
+ https://sinusoid.es/mixco/script/maudio_xponent.mixco.html
+ https://github.com/arximboldi/mixco/issues
+
+
+
+
+
+
+
+ [Master]
+ headMix
+ 0xb2
+ 0xd
+
+
+
+
+
+ [Master]
+ crossfader
+ 0xb2
+ 0x7
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ super1
+ 0xb0
+ 0xc
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xb0
+ 0xd
+
+
+
+
+
+ [EffectRack1_EffectUnit2]
+ super1
+ 0xb1
+ 0xc
+
+
+
+
+
+ [EffectRack1_EffectUnit2]
+ mix
+ 0xb1
+ 0xd
+
+
+
+
+
+ [EffectRack1_EffectUnit1_Effect1]
+ parameter1
+ 0xb2
+ 0x9
+
+
+
+
+
+ [EffectRack1_EffectUnit1_Effect1]
+ parameter2
+ 0xb2
+ 0x8
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel1]_enable
+ 0x92
+ 0x0
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel2]_enable
+ 0x92
+ 0x1
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x2c
+ 0x90
+ 0x2c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x2c
+ 0x80
+ 0x2c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x14
+ 0x90
+ 0x14
+
+
+
+
+
+ [Channel1]
+ filterLowKill
+ 0x90
+ 0x8
+
+
+
+
+
+ [Channel1]
+ filterLowKill
+ 0x80
+ 0x8
+
+
+
+
+
+ [Channel1]
+ filterMidKill
+ 0x90
+ 0x9
+
+
+
+
+
+ [Channel1]
+ filterMidKill
+ 0x80
+ 0x9
+
+
+
+
+
+ [Channel1]
+ filterHighKill
+ 0x90
+ 0xa
+
+
+
+
+
+ [Channel1]
+ filterHighKill
+ 0x80
+ 0xa
+
+
+
+
+
+ [Channel1]
+ pregain_toggle
+ 0x90
+ 0xb
+
+
+
+
+
+ [Channel1]
+ pregain_toggle
+ 0x80
+ 0xb
+
+
+
+
+
+ [Channel1]
+ filterLow
+ 0xb0
+ 0x8
+
+
+
+
+
+ [Channel1]
+ filterMid
+ 0xb0
+ 0x9
+
+
+
+
+
+ [Channel1]
+ filterHigh
+ 0xb0
+ 0xa
+
+
+
+
+
+ [Channel1]
+ pregain
+ 0xb0
+ 0xb
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x90
+ 0x2
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x80
+ 0x2
+
+
+
+
+
+ [Channel1]
+ volume
+ 0xb0
+ 0x7
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x7
+ 0x90
+ 0x7
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x7
+ 0x80
+ 0x7
+
+
+
+
+
+ [Channel1]
+ back
+ 0x90
+ 0x21
+
+
+
+
+
+ [Channel1]
+ back
+ 0x80
+ 0x21
+
+
+
+
+
+ [Channel1]
+ fwd
+ 0x90
+ 0x22
+
+
+
+
+
+ [Channel1]
+ fwd
+ 0x80
+ 0x22
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x17
+ 0x90
+ 0x17
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x17
+ 0x80
+ 0x17
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x18
+ 0x90
+ 0x18
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x18
+ 0x80
+ 0x18
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x19
+ 0x90
+ 0x19
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x19
+ 0x80
+ 0x19
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1a
+ 0x90
+ 0x1a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1a
+ 0x80
+ 0x1a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1b
+ 0x90
+ 0x1b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1b
+ 0x80
+ 0x1b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1c
+ 0x90
+ 0x1c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1c
+ 0x80
+ 0x1c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1d
+ 0x90
+ 0x1d
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1d
+ 0x80
+ 0x1d
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1e
+ 0x90
+ 0x1e
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x1e
+ 0x80
+ 0x1e
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x90
+ 0x1f
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x80
+ 0x1f
+
+
+
+
+
+ [Channel1]
+ reverse
+ 0x90
+ 0x20
+
+
+
+
+
+ [Channel1]
+ reverse
+ 0x80
+ 0x20
+
+
+
+
+
+ [Channel1]
+ cue_default
+ 0x90
+ 0x23
+
+
+
+
+
+ [Channel1]
+ cue_default
+ 0x80
+ 0x23
+
+
+
+
+
+ [Channel1]
+ play
+ 0x90
+ 0x24
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x29
+ 0x90
+ 0x29
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x29
+ 0x80
+ 0x29
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x2b
+ 0x90
+ 0x2b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x2b
+ 0x80
+ 0x2b
+
+
+
+
+
+ [Channel1]
+ reloop_exit
+ 0x90
+ 0x2a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x25
+ 0x90
+ 0x25
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x25
+ 0x80
+ 0x25
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x26
+ 0x90
+ 0x26
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x26
+ 0x80
+ 0x26
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x27
+ 0x90
+ 0x27
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x27
+ 0x80
+ 0x27
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x28
+ 0x90
+ 0x28
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x28
+ 0x80
+ 0x28
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel1]_enable
+ 0x90
+ 0xc
+
+
+
+
+
+ [EffectRack1_EffectUnit2]
+ group_[Channel1]_enable
+ 0x90
+ 0xd
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_xb0_xe
+ 0xb0
+ 0xe
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_xe
+ 0x90
+ 0xe
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_xe
+ 0x80
+ 0xe
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ super1
+ 0xb0
+ 0xf
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x90
+ 0xf
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x80
+ 0xf
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x15
+ 0x90
+ 0x15
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x16
+ 0x90
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x16
+ 0x80
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_xb0_x16
+ 0xb0
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x10
+ 0x90
+ 0x10
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x10
+ 0x80
+ 0x10
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x11
+ 0x90
+ 0x11
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x11
+ 0x80
+ 0x11
+
+
+
+
+
+ [Channel1]
+ rate
+ 0xe0
+ 0x0
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x12
+ 0x90
+ 0x12
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x12
+ 0x80
+ 0x12
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x13
+ 0x90
+ 0x13
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x90_x13
+ 0x80
+ 0x13
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x2c
+ 0x91
+ 0x2c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x2c
+ 0x81
+ 0x2c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x14
+ 0x91
+ 0x14
+
+
+
+
+
+ [Channel2]
+ filterLowKill
+ 0x91
+ 0x8
+
+
+
+
+
+ [Channel2]
+ filterLowKill
+ 0x81
+ 0x8
+
+
+
+
+
+ [Channel2]
+ filterMidKill
+ 0x91
+ 0x9
+
+
+
+
+
+ [Channel2]
+ filterMidKill
+ 0x81
+ 0x9
+
+
+
+
+
+ [Channel2]
+ filterHighKill
+ 0x91
+ 0xa
+
+
+
+
+
+ [Channel2]
+ filterHighKill
+ 0x81
+ 0xa
+
+
+
+
+
+ [Channel2]
+ pregain_toggle
+ 0x91
+ 0xb
+
+
+
+
+
+ [Channel2]
+ pregain_toggle
+ 0x81
+ 0xb
+
+
+
+
+
+ [Channel2]
+ filterLow
+ 0xb1
+ 0x8
+
+
+
+
+
+ [Channel2]
+ filterMid
+ 0xb1
+ 0x9
+
+
+
+
+
+ [Channel2]
+ filterHigh
+ 0xb1
+ 0xa
+
+
+
+
+
+ [Channel2]
+ pregain
+ 0xb1
+ 0xb
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x91
+ 0x2
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x81
+ 0x2
+
+
+
+
+
+ [Channel2]
+ volume
+ 0xb1
+ 0x7
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x7
+ 0x91
+ 0x7
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x7
+ 0x81
+ 0x7
+
+
+
+
+
+ [Channel2]
+ back
+ 0x91
+ 0x21
+
+
+
+
+
+ [Channel2]
+ back
+ 0x81
+ 0x21
+
+
+
+
+
+ [Channel2]
+ fwd
+ 0x91
+ 0x22
+
+
+
+
+
+ [Channel2]
+ fwd
+ 0x81
+ 0x22
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x17
+ 0x91
+ 0x17
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x17
+ 0x81
+ 0x17
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x18
+ 0x91
+ 0x18
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x18
+ 0x81
+ 0x18
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x19
+ 0x91
+ 0x19
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x19
+ 0x81
+ 0x19
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1a
+ 0x91
+ 0x1a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1a
+ 0x81
+ 0x1a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1b
+ 0x91
+ 0x1b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1b
+ 0x81
+ 0x1b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1c
+ 0x91
+ 0x1c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1c
+ 0x81
+ 0x1c
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1d
+ 0x91
+ 0x1d
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1d
+ 0x81
+ 0x1d
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1e
+ 0x91
+ 0x1e
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x1e
+ 0x81
+ 0x1e
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x91
+ 0x1f
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x81
+ 0x1f
+
+
+
+
+
+ [Channel2]
+ reverse
+ 0x91
+ 0x20
+
+
+
+
+
+ [Channel2]
+ reverse
+ 0x81
+ 0x20
+
+
+
+
+
+ [Channel2]
+ cue_default
+ 0x91
+ 0x23
+
+
+
+
+
+ [Channel2]
+ cue_default
+ 0x81
+ 0x23
+
+
+
+
+
+ [Channel2]
+ play
+ 0x91
+ 0x24
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x29
+ 0x91
+ 0x29
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x29
+ 0x81
+ 0x29
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x2b
+ 0x91
+ 0x2b
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x2b
+ 0x81
+ 0x2b
+
+
+
+
+
+ [Channel2]
+ reloop_exit
+ 0x91
+ 0x2a
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x25
+ 0x91
+ 0x25
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x25
+ 0x81
+ 0x25
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x26
+ 0x91
+ 0x26
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x26
+ 0x81
+ 0x26
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x27
+ 0x91
+ 0x27
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x27
+ 0x81
+ 0x27
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x28
+ 0x91
+ 0x28
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x28
+ 0x81
+ 0x28
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel2]_enable
+ 0x91
+ 0xc
+
+
+
+
+
+ [EffectRack1_EffectUnit2]
+ group_[Channel2]_enable
+ 0x91
+ 0xd
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_xb1_xe
+ 0xb1
+ 0xe
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_xe
+ 0x91
+ 0xe
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_xe
+ 0x81
+ 0xe
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ super1
+ 0xb1
+ 0xf
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x91
+ 0xf
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x81
+ 0xf
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x15
+ 0x91
+ 0x15
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x16
+ 0x91
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x16
+ 0x81
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_xb1_x16
+ 0xb1
+ 0x16
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x10
+ 0x91
+ 0x10
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x10
+ 0x81
+ 0x10
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x11
+ 0x91
+ 0x11
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x11
+ 0x81
+ 0x11
+
+
+
+
+
+ [Channel2]
+ rate
+ 0xe1
+ 0x0
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x12
+ 0x91
+ 0x12
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x12
+ 0x81
+ 0x12
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x13
+ 0x91
+ 0x13
+
+
+
+
+
+ [Master]
+ maudio_xponent.__handle_x91_x13
+ 0x81
+ 0x13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/controllers/mixco/README.md b/res/controllers/mixco/README.md
new file mode 100644
index 000000000000..9fc615249542
--- /dev/null
+++ b/res/controllers/mixco/README.md
@@ -0,0 +1,18 @@
+
+Mixco Scripts
+=============
+
+Some of the scripts in the parent folder are the compile output of
+**Mixco**, a tool that can generate the `.xml` and `.js` files from a
+single source file, among other things. This folder contains the
+original sources for such scripts.
+
+If you modify these scripts, you need to use the `mixco` command to
+compile the `.xml` and `.js` files that Mixxx can read. To install
+it, you need [NPM](https://www.npmjs.org/) and then:
+```sh
+ $ npm install -g mixco
+```
+
+You can find more information on how to install and use this
+tool [in the offical Mixco website](https://sinusoid.es/mixco/).
diff --git a/res/controllers/mixco/korg_nanokontrol2.mixco.litcoffee b/res/controllers/mixco/korg_nanokontrol2.mixco.litcoffee
new file mode 100644
index 000000000000..835c39e3ee70
--- /dev/null
+++ b/res/controllers/mixco/korg_nanokontrol2.mixco.litcoffee
@@ -0,0 +1,298 @@
+script.nanokontrol2
+===================
+
+> This file is part of the [Mixco framework](http://sinusoid.es/mixco).
+> - **View me [on a static web](http://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html)**
+> - **View me [on GitHub](https://github.com/arximboldi/mixco/blob/master/script/korg_nanokontrol2.mixco.litcoffee)**
+
+Mixxx script file for the **Korg NanoKontrol2** controller.
+
+This script description is a bit more verbose than others, at it tries
+to serve as **tutorial** on how to write your own controller scripts.
+People just interested in the functionallity of the mapping can find
+this in indented bullet points.
+
+ 
+
+Dependencies
+------------
+
+First, we have to import he *Mixco* modules that we are going to use,
+using the [NodeJS,
+**require**](http://nodejs.org/api/modules.html#modules_module_require_id)
+function. Also, lets define these couple of shortcuts to save typing.
+
+ mixco = require 'mixco'
+ {assert} = mixco.util
+ c = mixco.control
+ b = mixco.behaviour
+ v = mixco.value
+
+The script
+----------
+
+### Declaration
+
+We define the script with the **script.register** function, which will
+create the script instance. As first parameter we pass the current
+module, that is contained in the special *NodeJS* variable
+`module`. The second parameter is an object with the actual script.
+
+ mixco.script.register module,
+
+### Metadata
+
+Then we fill out the metadata. This will be shown to the user in the
+preferences window in Mixxx when he selects the script.
+
+ info:
+ name: '[mixco] Korg Nanokontrol 2'
+ author: 'Juan Pedro Bolivar Puente '
+ wiki: 'https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html'
+ forums: 'https://github.com/arximboldi/mixco/issues'
+ description:
+ """
+ Controller mapping for Korg Nanokontrol 2. Unlike
+ other scripts that are oriented as a secondary
+ controller, this provides basic deck controls, being
+ usable as primary interface.
+ """
+
+### Constructor
+
+All the actual interesting stuff happens in the *constructor* of the
+script. Here we will create the controls and add them to the script
+and define their behaviour.
+
+ constructor: ->
+
+#### Master section
+
+In this section we describe controls that have effect on the master
+channel and main outputs.
+
+##### Transport section
+
+All the buttons on the left side of the controllers is what we call
+the *transport section*. These are global buttons
+
+* The *cycle* button will be used as modifier.
+
+ @cycle = b.modifier()
+ c.control(0x2e).does @cycle
+
+Most of the transport controls will have their behaviour defined
+per-deck. We define them here and add the behaviours later.
+
+ @backButton = c.control 0x3a
+ @fwdButton = c.control 0x3b
+ @nudgeDownButton = c.control 0x2b
+ @nudgeUpButton = c.control 0x2c
+
+* The *marker* section can be used to browse the library. The left
+ and right arrows browse the playlist up and down. When *set* is
+ pressed, they move the sidebar.
+
+ @marker = b.modifier()
+ c.control(0x3C).does @marker
+
+ g = "[Playlist]"
+ c.control(0x3D)
+ .when(@marker, g, "SelectPrevPlaylist")
+ .else g, "SelectPrevTrack"
+ c.control(0x3E)
+ .when(@marker, g, "SelectNextPlaylist")
+ .else g, "SelectNextTrack"
+
+ @loadTrack = c.control(0x2a)
+
+Here are some more controls that get their actual functionallity
+defined later.
+
+ @sync = c.control(0x29)
+ @syncTempo = c.control(0x2d)
+
+##### Channel sections
+
+And finally, some of the master functionality are mapped to the
+channel sliders.
+
+* The *headphone gain* is mapped to the 7th slider.
+
+ g = "[Master]"
+ c.input(0x06).does g, "headVolume"
+
+* The *headphone mix* is mapped to the 6th slider.
+
+ c.input(0x05).does g, "headMix"
+
+* The *crossfader* is mapped to the 2nd slider.
+
+ c.input(0x02).does b.soft g, "crossfader"
+
+* The main *balance* is mapped to the 1st slider.
+
+ c.input(0x01).does b.soft g, "balance"
+
+
+#### Deck controls
+
+Then, we create a chooser object over the *pfl* (headphone) parameter,
+so we will have only one deck with PFL activated at a time.
+Also, this will let us change the behaviour of some *transport*
+controls depending on which deck is *selected* -- i.e, has PFL
+enabled.
+
+ @decks = b.chooser()
+
+Finally we add the per-deck controls, that are defined in `addDeck`.
+
+ @addDeck 0
+ @addDeck 1
+
+ addDeck: (i) ->
+ assert i in [0, 1]
+
+ g = "[Channel#{i+1}]"
+ offset = if i == 0 then [3, 2, 1, 0] else [4, 5, 6, 7]
+
+##### Channel sections
+
+* The top 8 knobs are mapped to the two decks mixer filter section
+ (low, mid, high, gain). They spread out from the center, i.e. the
+ 4th and 5th knob control the low EQ filter, the 3rd and 6th knob
+ control the mid EQ filter, and so on.
+
+ c.input(0x10 + offset[0]).does g, "filterLow"
+ c.input(0x10 + offset[1]).does g, "filterMid"
+ c.input(0x10 + offset[2]).does g, "filterHigh"
+ c.input(0x10 + offset[3]).does b.soft g, "pregain"
+
+* Then two central channel sections (4th and 5th) control the
+ following parameters of the left and right deck:
+
+ * S: Selects the deck *PFL*.
+ * M: *Cue* button for the deck.
+ * R: *Play* button for the deck.
+ * The fader controls the *volume* of the deck.
+
+ c.control(0x20 + offset[0]).does @decks.add g, "pfl"
+ c.control(0x30 + offset[0]).does g, "cue_default", g, "cue_indicator"
+ c.control(0x40 + offset[0]).does g, "play"
+ c.input(0x00 + offset[0]).does g, "volume"
+
+* The two furthest channel sections (1st and 8th) control the pitch
+related stuff of the two decks.
+
+ * S: *Bpm tap*, also shows the speed.
+ * M: Toggles *key lock*.
+ * R: Sets the *beat grid* to match the current playhead position.
+ * The fader controls the *pitch* of the deck.
+
+ c.control(0x20 + offset[3]).does g, "bpm_tap", g, "beat_active"
+ c.control(0x30 + offset[3]).does g, "keylock"
+ c.control(0x40 + offset[3]).does g, "beats_translate_curpos"
+ c.input(0x00 + offset[3]).does b.soft g, "rate"
+
+Then, we have some looping related buttons in the middle. Also, these
+are the hotcue trigger and clear with the *cycle* and *marker*
+modifiers.
+
+* The *S, M, R* buttons of the central channels (2nd, 3rd, 6th, 7th)
+ have different functionality, depending on the modifiers.
+ * Normally, they *toggle loops* of size 1, 2, 4 and 8 beats. The *R*
+buttons of these sections control *loop double* and *halve.*
+ * When the *cycle* button is held, they *launch hot-cues*.
+ * When the *set* button is held, they *clear hot-cues*.
+
+ c.control(0x20 + offset[1])
+ .when(@cycle, g, "hotcue_1_activate", g, "hotcue_1_enabled")
+ .else.when(@marker, g, "hotcue_1_clear", g, "hotcue_1_enabled")
+ .else g, "beatloop_2_toggle", g, "beatloop_2_enabled"
+ c.control(0x20 + offset[2])
+ .when(@cycle, g, "hotcue_2_activate", g, "hotcue_2_enabled")
+ .else.when(@marker, g, "hotcue_2_clear", g, "hotcue_2_enabled")
+ .else g, "beatloop_4_toggle", g, "beatloop_4_enabled"
+ c.control(0x30 + offset[1])
+ .when(@cycle, g, "hotcue_3_activate", g, "hotcue_3_enabled")
+ .else.when(@marker, g, "hotcue_3_clear", g, "hotcue_3_enabled")
+ .else g, "beatloop_8_toggle", g, "beatloop_8_enabled"
+ c.control(0x30 + offset[2])
+ .when(@cycle, g, "hotcue_4_activate", g, "hotcue_4_enabled")
+ .else.when(@marker, g, "hotcue_4_clear", g, "hotcue_4_enabled")
+ .else g, "beatloop_16_toggle", g, "beatloop_16_enabled"
+ c.control(0x40 + offset[1])
+ .when(@cycle, g, "hotcue_5_activate", g, "hotcue_5_enabled")
+ .else.when(@marker, g, "hotcue_5_clear", g, "hotcue_5_enabled")
+ .else g, "loop_halve"
+ c.control(0x40 + offset[2])
+ .when(@cycle, g, "hotcue_6_activate", g, "hotcue_6_enabled")
+ .else.when(@marker, g, "hotcue_6_clear", g, "hotcue_6_enabled")
+ .else g, "loop_double"
+
+##### Transport section
+
+These per-deck controls of the transport section have effect on the
+*selected track*. We consider the current PFL track to be the
+selected track.
+
+The *<<* and *>>* buttons are a bit more complicated. We want them
+to behave as *nudge* buttons for the selected track, but we want the
+*cycle* modifier to change the nudge speed.
+
+See how we use the `behaviour.and` condition combinator to mix the
+conditions. We also use `control.else.when` to simplify the negative
+condition.
+
+* The *<<* and *>>* buttons nudge and scroll over the selected track.
+
+ chooseCycle = v.and @cycle, @decks.activator i
+ @nudgeUpButton
+ .when(chooseCycle, b.toggle 0, 0.5, g, "wheel")
+ .else.when @decks.activator(i), b.toggle 0, 0.1, g, "wheel"
+ @nudgeDownButton
+ .when(chooseCycle, b.toggle 0, -0.5, g, "wheel")
+ .else.when @decks.activator(i), b.toggle 0, -0.1, g, "wheel"
+
+* The *track<* and *track>* buttons control the selected track *fast
+ forward* and *fast rewind*.
+
+ @fwdButton.when @decks.activator(i), g, "fwd"
+ @backButton.when @decks.activator(i), g, "back"
+
+* Load *stop* button loads the selected track in the selected deck.
+
+ @loadTrack.when @decks.activator(i), g, "LoadSelectedTrack"
+
+* The *play* and *record* buttons synchronize to the other track. The
+ *play* button can be held to enable master synchronization for the deck.
+
+ @sync.when @decks.activator(i), g, "sync_enabled"
+ @syncTempo.when @decks.activator(i), g, "beatsync"
+
+### Initialization
+
+The **init** method is called by Mixxx when the script is loaded. Here
+we can initialize the state of Mixxx. In our case, we select the first
+deck, such that all transport buttons are directly functional.
+
+ init: ->
+ @decks.activate 0
+
+License
+-------
+
+> Copyright (C) 2013 Juan Pedro Bolívar Puente
+>
+> This program is free software: you can redistribute it and/or
+> modify it under the terms of the GNU General Public License as
+> published by the Free Software Foundation, either version 3 of the
+> License, or (at your option) any later version.
+>
+> This program is distributed in the hope that it will be useful,
+> but WITHOUT ANY WARRANTY; without even the implied warranty of
+> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+> GNU General Public License for more details.
+>
+> You should have received a copy of the GNU General Public License
+> along with this program. If not, see .
diff --git a/res/controllers/mixco/maudio_xponent.mixco.litcoffee b/res/controllers/mixco/maudio_xponent.mixco.litcoffee
new file mode 100644
index 000000000000..88f0ce116171
--- /dev/null
+++ b/res/controllers/mixco/maudio_xponent.mixco.litcoffee
@@ -0,0 +1,393 @@
+script.xponent
+==============
+
+> This file is part of the [Mixco framework](http://sinusoid.es/mixco).
+> - **View me [on a static web](http://sinusoid.es/mixco/script/maudio_xponent.mixco.html)**
+> - **View me [on GitHub](https://github.com/arximboldi/mixco/blob/master/script/maudio_xponent.mixco.litcoffee)**
+
+Mixxx script file for the **M-Audio Xponent** controller. The numbers
+in the following picture will be used in the script to describe the
+functionallity of the controls.
+
+ 
+
+ mixco = require 'mixco'
+ {assert} = mixco.util
+ c = mixco.control
+ b = mixco.behaviour
+ v = mixco.value
+
+ mixco.script.register module,
+
+ info:
+ name: '[mixco] M-Audio Xponent'
+ author: 'Juan Pedro Bolivar Puente '
+ wiki: 'https://sinusoid.es/mixco/script/maudio_xponent.mixco.html'
+ forums: 'https://github.com/arximboldi/mixco/issues'
+ description:
+ """
+ Controller mapping for the M-Audio Xponent DJ controller.
+ """
+
+Global section
+--------------
+
+Controls that do not have a per-deck functionality.
+
+ constructor: ->
+ ccId = (cc) -> c.ccIds cc, 2
+ g = "[Master]"
+
+* **27.** Headphone mix.
+
+ c.input(ccId 0x0D).does g, "headMix"
+
+* **39.** Crossfader.
+
+ c.input(ccId 0x07).does g, "crossfader"
+
+### Effects
+
+Most of knobs and buttons in **24** and **25** are dedicated to
+effects. Some of them are mapped per-deck --see later-- but some are
+mapped globally:
+
+* The *first and second knobs* of the *left deck* control the *super*
+ and *mix* of the first effect unit. In the *right deck*, they do
+ likewise for the second effect unit.
+
+ c.input(0x0c, 0x00).does \
+ b.soft "[EffectRack1_EffectUnit1]", "super1"
+ c.input(0x0d, 0x00).does \
+ b.soft "[EffectRack1_EffectUnit1]", "mix"
+
+ c.input(0x0c, 0x01).does \
+ b.soft "[EffectRack1_EffectUnit2]", "super1"
+ c.input(0x0d, 0x01).does \
+ b.soft "[EffectRack1_EffectUnit2]", "mix"
+
+* **16.** When in *MIDI mode*, the touch pad can be used to control
+ the first two parameters of the first effect. *MIDI mode* can be
+ enabled with the button labeled `MIDI` below the touch pad.
+ Otherwise, the touch pad is used to control the computer mouse.
+
+ c.control(0x09, 0x02)
+ .does "[EffectRack1_EffectUnit1_Effect1]", "parameter1"
+ c.control(0x08, 0x02)
+ .does "[EffectRack1_EffectUnit1_Effect1]", "parameter2"
+
+* **17.** and **18.** When in *MIDI mode*, the touch pad buttons *toggle
+ the first effect unit* for the first and second deck respectively.
+
+ c.input(c.noteOnIds 0x00, 0x02)
+ .does "[EffectRack1_EffectUnit1]", "group_[Channel1]_enable"
+ c.input(c.noteOnIds 0x01, 0x02)
+ .does "[EffectRack1_EffectUnit1]", "group_[Channel2]_enable"
+
+Per deck controls
+-----------------
+
+We add the two decks with the `addDeck(idx)` function. In the
+*Xponent*, each MIDI message is repeated per-deck on a different
+channel.
+
+ @decks = b.chooser()
+ @addDeck 0
+ @addDeck 1
+
+ addDeck: (i) ->
+ assert i in [0, 1]
+ g = "[Channel#{i+1}]"
+ ccId = (cc) -> c.ccIds cc, i
+ noteId = (note) -> c.noteIds note, i
+ noteOnId = (note) -> c.noteOnIds note, i
+
+* **15.** Shift. It changes the behaviour of some controls. Note
+ that there is a shift button per-deck, which only affects the
+ controls of that deck.
+
+ shift = b.modifier()
+ c.control(noteId 0x2C).does shift
+
+* **12.** Pre-Fade Listen. Select which deck goes to the headphones.
+
+ c.control(noteOnId 0x14).does @decks.add g, "pfl"
+
+### The mixer
+
+
+* **20.** Filter and gain kills.
+
+ c.control(noteId 0x08).does g, "filterLowKill"
+ c.control(noteId 0x09).does g, "filterMidKill"
+ c.control(noteId 0x0A).does g, "filterHighKill"
+ c.control(noteId 0x0B).does g, "pregain_toggle"
+
+* **22.** Mixer EQ and gain.
+
+ c.input(ccId 0x08).does g, "filterLow"
+ c.input(ccId 0x09).does g, "filterMid"
+ c.input(ccId 0x0A).does g, "filterHigh"
+ c.input(ccId 0x0B).does b.soft g, "pregain"
+
+* **23.** Per deck volume meters.
+
+ c.output(c.ccIds 0x12+i, 3)
+ .does b.mapOut(g, "VuMeter").meter()
+
+* **34.** Sync button. Like the button in the UI, it can be held
+ pressed to enable the deck in the *master sync* group.
+
+ c.control(noteId 0x02).does g, "sync_enabled"
+
+* **33.** Deck volume.
+
+ c.input(ccId 0x07).does b.soft g, "volume"
+
+* **38.** Punch-in/transform. While pressed, lets this track be heard
+ overriding the crossfader.
+
+ c.control(noteId 0x07).does b.punchIn (0.5-i)
+
+### The transport section
+
+* **29.** Song progress indication. When it approches the end of the
+ playing song it starts blinking.
+
+ c.output(c.ccIds 0x14+i, 3).does b.playhead g
+
+* **30.** Back and forward.
+
+ c.control(noteId 0x21).does g, "back"
+ c.control(noteId 0x22).does g, "fwd"
+
+* **31.** Includes several buttons...
+
+- The top buttons with numbers are the *hotcues*. On first press,
+ sets the hotcue. On second press, jumps to hotcue. When *shift* is
+ held, deletes the hotcue point.
+
+ for idx in [0..4]
+ c.control(noteId(0x17 + idx))
+ .when(shift,
+ g, "hotcue_#{idx+1}_clear",
+ g, "hotcue_#{idx+1}_enabled")
+ .else g, "hotcue_#{idx+1}_activate",
+ g, "hotcue_#{idx+1}_enabled"
+
+- The little arrow buttons do *beatjump* -- jump forward or back by
+ 4 beats. When *shift* is pressed they jump by one beat.
+
+ c.control(noteId 0x1C)
+ .when shift, g, "beatjump_1_backward"
+ .else g, "beatjump_4_backward"
+ c.control(noteId 0x1D)
+ .when shift, g, "beatjump_1_forward"
+ .else g, "beatjump_4_forward"
+
+- The *lock* button does *key lock* -- i.e. makes tempo changes
+ independent of pitch. When *shift* is pressed, it expands/collapses
+ the selected browser item.
+
+ c.control(noteId 0x1E)
+ .when(shift, "[Playlist]", "ToggleSelectedSidebarItem")
+ .else g, "keylock"
+
+- The *plus* (+) button moves the beat grid to align with the current
+ play position.
+
+ c.control(noteId 0x1F).does g, "beats_translate_curpos"
+
+- The *minus* (-) button plays the track in reverese.
+
+ c.control(noteId 0x20).does g, "reverse"
+
+* **35.** Cue button.
+
+ c.control(noteId 0x23).does g, "cue_default", g, "cue_indicator"
+
+* **37.** Play/pause button.
+
+ c.control(noteOnId 0x24).does g, "play"
+
+
+### The looping section
+
+* **36.** This includes several controls to manage loops...
+
+- The *in* and *out* buttons set the loop start and end to the
+ current playing position. When *shift* is pressed, they halve and
+ double the current loop size respectively.
+
+ c.control(noteId 0x29)
+ .when(shift, g, "loop_halve")
+ .else g, "loop_in"
+ c.control(noteId 0x2B)
+ .when(shift, g, "loop_double")
+ .else g, "loop_out"
+
+- The *loop* toggles the current loop on/off whenever there is a loop
+ selected.
+
+ c.control(noteOnId 0x2A)
+ .does g, "reloop_exit", g, "loop_enabled"
+
+- The numbers set and trigger a loop of 4, 8, 16 and 32 beats
+ respectively. When *shift*, they set loops of 1/8, 1/2, 1 or 2
+ beats long.
+
+ c.control(noteId 0x25)
+ .when(shift, g, "beatloop_0.125_activate",
+ g, "beatloop_0.125_enabled")
+ .else g, "beatloop_4_activate",
+ g, "beatloop_4_enabled"
+ c.control(noteId 0x26)
+ .when(shift, g, "beatloop_0.5_activate",
+ g, "beatloop_0.5_enabled")
+ .else g, "beatloop_8_activate",
+ g, "beatloop_8_enabled"
+ c.control(noteId 0x27)
+ .when(shift, g, "beatloop_1_activate",
+ g, "beatloop_1_enabled")
+ .else g, "beatloop_16_activate",
+ g, "beatloop_16_enabled"
+ c.control(noteId 0x28)
+ .when(shift, g, "beatloop_2_activate",
+ g, "beatloop_2_enabled")
+ .else g, "beatloop_32_activate",
+ g, "beatloop_32_enabled"
+
+### Effects
+
+* In the **24** group, the *first* and *second* buttons enable the
+ first or second effect units for this deck.
+
+ c.control(noteOnId 0x0c)
+ .does "[EffectRack1_EffectUnit1]", "group_#{g}_enable"
+ c.control(noteOnId 0x0d)
+ .does "[EffectRack1_EffectUnit2]", "group_#{g}_enable"
+
+* The *third knob and button* in **24** and **25** enable a *beat
+ roll* effect, similar to those of the looping section but with
+ resolution controllable with a knob for more drastic effects, and
+ the play position is restored when turned off.
+
+ beatloop = b.beatEffect g, 'roll'
+ c.input(ccId 0x0e).does beatloop.selector()
+ c.control(noteId 0x0e).does beatloop
+
+* The *fourth knob and button* in **24** and **25** enable the quick
+ effect knob -- by default mapped to a filter sweep.
+
+ c.input(ccId 0x0f)
+ .does "[QuickEffectRack1_#{g}]", 'super1'
+ c.control(noteId 0x0f)
+ .does "[QuickEffectRack1_#{g}]", 'enabled'
+
+### The wheel and pitch section
+
+* **10.** Toggles *scratch* mode.
+
+ scratchMode = b.switch()
+ c.control(noteOnId 0x15).does scratchMode
+
+* **11.** The wheel does different functions...
+
+ - When the deck is stopped, it moves the play position.
+
+ - When *scratch* mode is on, it will stop the song when touched on
+ top and control the track play like a vinyl when moved.
+
+ - Otherwise, it can be used to *nudge* the playing speed up or down
+ to sync the phase of tracks when the track is playing.
+
+ - When *shift* is pressed, it will scroll through the current list
+ of tracks in the browser.
+
+ selectTrackKnobTransform = do ->
+ toggle = 1
+ (ev) ->
+ val = ev.value - 64
+ toggle -= 1
+ if toggle < 0 then toggle = 3
+ if toggle == 0 then val.sign() else null
+
+ c.control(noteId 0x16)
+ .when v.and(v.not(shift), scratchMode), b.scratchEnable i+1
+
+ c.input(ccId 0x16)
+ .when(shift, b.map("[Playlist]", "SelectTrackKnob")
+ .transform selectTrackKnobTransform)
+ .else.when(scratchMode,
+ b.scratchTick(i+1).options.spread64)
+ .else b.map(g, "jog").transform (ev) -> (ev.value - 64) / 8
+
+* **26.** Temporarily nudges the pitch down or up. When **shift**,
+they do it in a smaller amount.
+
+ c.control(noteId 0x10)
+ .when(shift, g, "rate_temp_down_small")
+ .else g, "rate_temp_down"
+ c.control(noteId 0x11)
+ .when(shift, g, "rate_temp_up_small")
+ .else g, "rate_temp_up"
+
+* **32.** Pitch slider, adjusts playing speed.
+
+ c.input(c.pbIds i).does b.soft g, "rate"
+
+* **21.** Custom effects that include...
+
+- The *big cross* (X) button simulates a *brake* effect as if the
+ turntable was turned off suddenly. On *shift*, it ejects the track
+ from the deck.
+
+ c.control(noteId 0x12)
+ .when(shift, g, "eject")
+ .else b.brake i+1
+
+- The *big minus* (--) button simulates a *backspin* effect as if the
+ vinyl was launched backwards. On *shift*, it loads the selected
+ track in the browser into the deck.
+
+ c.control(noteId 0x13)
+ .when(shift, g, "LoadSelectedTrack")
+ .else b.spinback i+1
+
+Initialization
+--------------
+
+Unlike old Mixxx versions, this script initializes the device properly
+for light feedback. The trick of holding the two and key button on
+initalization are no longer required.
+
+ preinit: ->
+ msg = [0xF0, 0x00, 0x20, 0x08, 0x00, 0x00, 0x63, 0x0E,
+ 0x16, 0x40, 0x00, 0x01, 0xF7]
+ @mixxx.midi.sendSysexMsg msg, msg.length
+
+ init: ->
+ @decks.activate 0
+
+ postshutdown: ->
+ msg = [0xF0, 0x00, 0x20, 0x08, 0x00, 0x00, 0x63, 0x0E,
+ 0x16, 0x40, 0x00, 0x00, 0xF7]
+ @mixxx.midi.sendSysexMsg msg, msg.length
+
+License
+-------
+
+> Copyright (C) 2013 Juan Pedro Bolívar Puente
+>
+> This program is free software: you can redistribute it and/or
+> modify it under the terms of the GNU General Public License as
+> published by the Free Software Foundation, either version 3 of the
+> License, or (at your option) any later version.
+>
+> This program is distributed in the hope that it will be useful,
+> but WITHOUT ANY WARRANTY; without even the implied warranty of
+> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+> GNU General Public License for more details.
+>
+> You should have received a copy of the GNU General Public License
+> along with this program. If not, see .
diff --git a/res/controllers/mixco/novation_twitch.mixco.js b/res/controllers/mixco/novation_twitch.mixco.js
new file mode 100644
index 000000000000..b7a9298f8023
--- /dev/null
+++ b/res/controllers/mixco/novation_twitch.mixco.js
@@ -0,0 +1,450 @@
+// script.twitch
+// =============
+//
+// > This file is part of the [Mixco framework](http://sinusoid.es/mixco).
+// > - **View me [on a static web](http://sinusoid.es/mixco/script/novation_twitch.mixco.html)**
+// > - **View me [on GitHub](https://github.com/arximboldi/mixco/blob/master/script/novation_twitch.mixco.litcoffee)**
+//
+// Mixx script file for the **Novation Twitch** controller.
+//
+// This script serves as **tutorial** for creating scripts using the
+// *Mixco* framework, but programming directly in JavaScript. Still,
+// we recommend you to try CoffeeScript, since it is a bit of a nicer
+// language.
+//
+// If you want to modify this script, you may want to read the
+// [Novation Twitch Programmer Guide](https://us.novationmusic.com/support/downloads/twitch-programmers-reference-guide)
+//
+// ### Note for Linux Users
+//
+// The Linux Kernel version 3.10 is required to get Novation Twitch
+// detected as soundcard or MIDI device.
+//
+// 
+//
+// Dependencies
+// ------------
+//
+// First, we have to import the modules from the framework. We use
+// that the *NodeJS* `require` function. Note that all other NodeJS
+// modules are usable too when writing your script with the *Mixco*
+// framework.
+
+var _ = require('underscore')
+var mixco = require('mixco')
+var c = mixco.control
+var b = mixco.behaviour
+var v = mixco.value
+
+// The script
+// ----------
+//
+// When writing a controller script we use the `script.register`
+// function to generate and install a script instance in the current
+// module. The first parameter is the current module as defined by
+// *NodeJS*, the second parameter is the JavaScript object with all
+// the functions and information about our script.
+
+mixco.script.register(module, {
+
+ // ### Metadata
+ //
+ // Then the `info` object contains the meta-data that is displayed
+ // to the user in the MIDI mapping chooser of Mixxx.
+
+ info: {
+ name: "[mixco] Novation Twitch",
+ author: "Juan Pedro Bolivar Puente ",
+ forums: 'https://github.com/arximboldi/mixco/issues',
+ wiki: 'https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html',
+ description: "Controller mapping for Novation Twitch (in basic mode).",
+ },
+
+ // ### Constructor
+ //
+ // The constructor contains the definition of the MIDI mapping.
+ // Here we create all the different control objects and add them
+ // to the script instance.
+
+ constructor: function () {
+
+ // #### Master section
+ //
+ // Many of the master controls of the that the *headphone
+ // volume*, *headphone mix*, *booth volume* and *master volume*
+ // knobs are handled directly by the integrated soundcard of
+ // the controller. We map the rest here.
+ //
+ // * *Crossfader* slider.
+
+ c.input(0x08, 0x07).does("[Master]", "crossfader")
+
+ // #### Mic/aux and effects
+ //
+ // Sadly, the buttons *Aux*, *Deck A*, *Deck B* and *PFL*
+ // of the effects and microphone sections are controlled by
+ // the hardware in a bit of a useless way, so they do nothing
+ // -- other than light up when they are pressed.
+
+ var ccIdFxBanks = function (index) {
+ banks = 5
+ params = 4
+ ids = []
+ for (var j = 0; j < banks; ++j)
+ ids.push.apply(ids, c.ccIds(index + params * j, 0xB))
+ return ids
+ }
+
+ // * Microphone *volume* control and *on/off* button.
+
+ c.input(ccIdFxBanks(0x3)).does(b.soft("[Microphone]", "pregain"))
+ c.control(c.noteIds(0x23, 0xB)).does("[Microphone]", "talkover")
+
+ // * The the *Depth* and *Mix* knobs in the *Master FX*
+ // section are mapped to *mix* and *super* of the first
+ // effect unit.
+
+ c.input(ccIdFxBanks(0x0))
+ .does("[EffectRack1_EffectUnit1]", "mix")
+ c.input(ccIdFxBanks(0x1))
+ .option(scaledDiff(1/2))
+ .does("[EffectRack1_EffectUnit1]", "super1")
+
+ // * The *beats* knob can be used to change the selected effect.
+
+ c.input(ccIdFxBanks(0x2))
+ .does("[EffectRack1_EffectUnit1]", "chain_selector")
+
+ // * The *on/off* button of the FX section completley toggles
+ // the first effect unit.
+
+ c.control(c.noteIds(0x22, 0xB))
+ .does("[EffectRack1_EffectUnit1]", "enabled")
+
+ // #### Browse
+ //
+ // * The *back* and *fwd* can be used to scroll the sidebar.
+
+ c.input(c.noteIds(0x54, 0x7)).does(
+ "[Playlist]", "SelectPrevPlaylist")
+ c.input(c.noteIds(0x56, 0x7)).does(
+ "[Playlist]", "SelectNextPlaylist")
+
+ // * The *scroll* encoder scrolls the current view. When
+ // pressed it moves faster.
+
+ scrollFaster = b.modifier()
+
+ c.input(c.noteIds(0x55, 0x7)).does(scrollFaster)
+ c.input(0x55, 0x7)
+ .when (scrollFaster,
+ b.map("[Playlist]", "SelectTrackKnob")
+ .option(scaledSelectKnob(8)))
+ .else_(b.map("[Playlist]", "SelectTrackKnob")
+ .options.selectknob)
+
+ // * The *area* toggles the maximized library.
+
+ c.control(c.noteIds(0x50, 0x7)).does(
+ "[Master]", "maximize_library")
+
+ // * The *view* button in the *browser* section lets you tap
+ // the tempo for the track that is currently on PFL.
+
+ this.viewButton = c.control(c.noteIds(0x51, 0x7))
+
+ // ### Per deck controls
+ //
+ // We use a `behaviou.chooser` for the PFL selection. This
+ // will make sure that only one deck's PFL is selected at
+ // a time for greater convenience. Then, we define a `addDeck`
+ // function that will add the actual controls for each of the
+ // decks.
+
+ this.decks = b.chooser()
+ this.addDeck(0)
+ this.addDeck(1)
+
+ },
+
+ addDeck: function (i) {
+ var g = "[Channel" + (i+1) + "]"
+ var ccId = function (cc) { return c.ccIds(cc, 0x07+i) }
+ var ccIdShift = function (cc) { return c.ccIds(cc, 0x09+i) }
+ var ccIdAll = function (cc) { return _.union(ccId(cc),
+ ccIdShift(cc)) }
+ var noteId = function (note) { return c.noteIds(note, 0x07+i) }
+ var noteIdShift = function (note) { return c.noteIds(note, 0x09+i) }
+ var noteIdAll = function (cc) { return _.union(noteId(cc),
+ noteIdShift(cc)) }
+
+ // #### Mixer section
+ //
+ // * PFL deck selection.
+
+ c.control(noteIdAll(0x0A)).does(this.decks.add(g, "pfl"))
+
+ this.viewButton.when(this.decks.activator(i),
+ g, "bpm_tap", g, "beat_active")
+
+ // * *Volume* fader and *low*, *mid*, *high* and *trim* knobs.
+ // *Trim* is the deck *gain* knob in Mixxx.
+
+ c.input(ccIdAll(0x07)).does(g, "volume")
+ c.input(ccIdAll(0x46)).does(g, "filterLow")
+ c.input(ccIdAll(0x47)).does(g, "filterMid")
+ c.input(ccIdAll(0x48)).does(g, "filterHigh")
+ c.input(ccIdAll(0x09)).does(g, "pregain")
+
+ // * *Volume* meters for each channel.
+
+ c.output(noteIdAll(0x5f)).does(b.mapOut(g, "VuMeter").meter())
+
+ // * The **fader FX** we use to control the quick filter. The
+ // **on/off** button below can be used to toggle it.
+ // Likewise, pressing the knob momentarily toggles it.
+
+ c.input(ccIdAll(0x06))
+ .option(scaledDiff(1/2))
+ .does("[QuickEffectRack1_"+g+"]", 'super1')
+ c.control(noteIdAll(0x06))
+ .does("[QuickEffectRack1_"+g+"]", 'enabled')
+ c.control(noteIdAll(0x0D))
+ .does("[QuickEffectRack1_"+g+"]", 'enabled')
+
+ // #### Effects
+ //
+ // * In the *Master FX* section, the *FX Select* left and
+ // right enable the first effect unit on the deck in the
+ // direction of the arrow.
+
+ c.control(c.noteIds(0x20+i, 0xB))
+ .does("[EffectRack1_EffectUnit1]", "group_"+g+"_enable")
+
+ // #### Browse
+ //
+ // * The *load A* or *load B* buttons load the selected track
+ // to the given deck.
+
+ c.control(c.noteIds(0x52+i, 0x7)).does(g, "LoadSelectedTrack")
+
+ // #### Deck transport
+ //
+ // * The *play* and *cue* buttons work as expected. On
+ // *shift*, the cue button does a reverse effect.
+
+ var redLed = 0x00
+ var amberLed = 0x40
+ var greenLed = 0x70
+ var pad = function (ids, color) {
+ return c.control(ids).states({
+ on: color + 0xf,
+ off: color + 0x1
+ })
+ }
+
+ pad(noteIdAll(0x17), greenLed).does(g, "play")
+ pad(noteId(0x16), redLed).does(g, "cue_default", g, "cue_indicator")
+ pad(noteIdShift(0x16), amberLed).does(g, "reverse")
+
+ // * The *keylock* button toggles the pitch-independent time
+ // stretching. On *shift*, it toggles *slip mode*, in which
+ // loops and scratching continue playback on the background
+ // thus returning the playhead to where the track would have
+ // been.
+
+ slipMode = b.switch_()
+ c.control(noteId(0x12)).does(g, "keylock")
+ c.control(noteIdShift(0x12)).does(slipMode)
+
+ // * The *sync* button. Like the button in the UI, it can be
+ // held pressed to enable the deck in the *master sync*
+ // group.
+
+ c.control(noteIdAll(0x13)).does(g, "sync_enabled")
+
+ // #### Beat grid
+ //
+ // * The *adjust* button *aligns the beatgrid* to the current
+ // play position.
+
+ c.control(noteIdAll(0x11)).does(g, "beats_translate_curpos")
+
+ // * The *set* button toggles loop and hot-cue *quantization*
+ // on or off.
+
+ c.control(noteIdAll(0x10)).does(g, "quantize")
+
+ // #### Pitch and transport bar
+ //
+ // * The *pitch* encoder moves the pitch slider up and
+ // down. When it is pressed, it moves it pitch faster.
+
+ var coarseRateFactor = 1/10
+ var coarseRateOn = b.modifier()
+
+ c.input(noteIdAll(0x03)).does(coarseRateOn)
+ c.input(ccIdAll(0x03))
+ .when (coarseRateOn,
+ b.map(g, "rate").option(scaledDiff(2)))
+ .else_(b.map(g, "rate").option(scaledDiff(1/12)))
+
+ // * In *drop* mode, the touch strip scrolls through the song.
+
+ c.input(ccId(0x34)).does(g, "playposition")
+
+ // * In *swipe* mode, the touch strip nudges the pitch up and
+ // down. When *shift* is held it simulates scratching.
+
+ c.input(ccId(0x35)).does(g, "jog")
+ .option(scaledSelectKnob(-1/3))
+ c.input(ccIdShift(0x35)).does(b.scratchTick(i+1))
+ .options.selectknob,
+ c.input(noteIdShift(0x47))
+ .does(b.scratchEnable(i+1, 128))
+ .when(slipMode, b.map(g, "slip_enabled").options.switch_)
+
+ // #### Performance modes
+ //
+ // ##### Hot cues
+ //
+ // * In *hot-cues* mode, the performance buttons control the
+ // hot cues. One may *clear* hot-cues with *shift*.
+
+ for (var j = 0; j < 8; ++j) {
+ pad(noteId(0x60+j), amberLed).does(
+ g, "hotcue_" + (j+1) + "_activate",
+ g, "hotcue_" + (j+1) + "_enabled")
+ pad(noteIdShift(0x60+j), amberLed).does(
+ g, "hotcue_" + (j+1) + "_clear",
+ g, "hotcue_" + (j+1) + "_enabled")
+ }
+
+ // ##### Slicer
+ //
+ // There is no functionality like a *slicer* in Mixxx, but we
+ // reuse these pads for various purposes in this mode.
+ //
+ // * The buttons *1 to 4* trigger the first four samplers.
+ // The sample plays as long as the button is held.
+
+ for (var j = 0; j < 4; ++j)
+ pad(noteIdAll(0x68+j), redLed).does(
+ "[Sampler" + (j+1) + "]", "cue_preview")
+
+ // * The buttons *5 and 6* trigger a *spinback* and *brake*
+ // effect respectively.
+
+ pad(noteIdAll(0x6C), greenLed).does(b.spinback(i+1))
+ pad(noteIdAll(0x6D), greenLed).does(b.brake(i+1))
+
+ // * The buttons *7 and 8* perform a stutter effect at
+ // different speeds.
+
+ pad(noteIdAll(0x6E), amberLed).does(b.stutter(g, 1/8))
+ pad(noteIdAll(0x6F), amberLed).does(b.stutter(g, 1/4))
+
+ // ##### Auto loop
+ //
+ // * In *auto-loop* mode, the pads select *loops* of sizes
+ // 0.5, 1, 2, 4, 8, 16, 32 or 64, beats (starting at the
+ // top-left pad). On *shift*, it creates loops of sizes
+ // 1/32, 1/16, 1/8, 1/4, 1/2, 1, 2, or 4 beats.
+
+ loopSize = [ "0.03125", "0.0625", "0.125", "0.25",
+ "0.5", "1", "2", "4",
+ "8", "16", "32", "64" ]
+ for (var j = 0; j < 8; ++j)
+ pad(noteId(0x70+j), greenLed).does(
+ g, "beatloop_" + loopSize[4+j] + "_toggle",
+ g, "beatloop_" + loopSize[4+j] + "_enabled")
+ for (var j = 0; j < 8; ++j)
+ pad(noteIdShift(0x70+j), greenLed).does(
+ g, "beatloop_" + loopSize[j] + "_toggle",
+ g, "beatloop_" + loopSize[j] + "_enabled")
+
+ // ##### Loop roll
+ //
+ // * In *loop-roll* mode, momentarily creates a loop and, on
+ // release returns the playhead to where it would have been
+ // without looping. Loop sizes are 1/32, 1/16, 1/8, 1/4,
+ // 1/2, 1, 2, or 4 beats (starting at the top-left pad). On
+ // *shift*, it is 0.5, 1, 2, 4, 8, 16, 32 or 64 beats.
+
+ loopSize = [ "0.03125", "0.0625", "0.125", "0.25",
+ "0.5", "1", "2", "4",
+ "8", "16", "32", "64" ]
+ for (var j = 0; j < 8; ++j)
+ pad(noteId(0x78+j), greenLed).does(
+ g, "beatlooproll_" + loopSize[j] + "_activate",
+ g, "beatloop_" + loopSize[j] + "_enabled")
+ for (var j = 0; j < 8; ++j)
+ pad(noteIdShift(0x78+j), greenLed).does(
+ g, "beatlooproll_" + loopSize[4+j] + "_activate",
+ g, "beatloop_" + loopSize[4+j] + "_enabled")
+
+ },
+
+ // ### Initialization
+ //
+ // The `preinit` function is called before the MIDI controls are
+ // initialized. We are going to set the device in *basic mode*,
+ // as mentioned in the manual. This means that mode management is
+ // done by the device -- this will simplify the script and let
+ // have direct lower latency mappings more often.
+
+ preinit: function () {
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x6f)
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x00)
+ },
+
+ init: function () {
+ this.decks.activate(0)
+ },
+
+ // ### Shutdown
+ //
+ // The documentation suggests to reset the device when the program
+ // shuts down. This means that all the lights are turned off and
+ // the device is in basic mode, ready to be used by some other
+ // program.
+
+ postshutdown: function () {
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x00)
+ }
+
+});
+
+// Utilities
+// ---------
+//
+// The *scaledDiff* function returns a behaviour option that is useful
+// to define encoders with a specific sensitivity, which is useful to
+// correct the issues of the stepped encoders.
+
+function scaledDiff (factor) {
+ return function (v, v0) {
+ return (v0 + factor * (v > 64 ? v - 128 : v)).clamp(0, 128)
+ }
+}
+
+function scaledSelectKnob (factor) {
+ return function (v) {
+ return factor * (v > 64 ? v - 128 : v)
+ }
+}
+
+// > Copyright (C) 2013 Juan Pedro Bolívar Puente
+// >
+// > This program is free software: you can redistribute it and/or
+// > modify it under the terms of the GNU General Public License as
+// > published by the Free Software Foundation, either version 3 of the
+// > License, or (at your option) any later version.
+// >
+// > This program is distributed in the hope that it will be useful,
+// > but WITHOUT ANY WARRANTY; without even the implied warranty of
+// > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// > GNU General Public License for more details.
+// >
+// > You should have received a copy of the GNU General Public License
+// > along with this program. If not, see .
diff --git a/res/controllers/novation_twitch.mixco.output.js b/res/controllers/novation_twitch.mixco.output.js
new file mode 100644
index 000000000000..ad56ba5fa438
--- /dev/null
+++ b/res/controllers/novation_twitch.mixco.output.js
@@ -0,0 +1,8582 @@
+/*
+ * File generated with Mixco framework version: 2.0.2
+ * More info at:
+ */
+
+MIXCO_SCRIPT_FILENAME = '/home/raskolnikov/dev/mixco/script/novation_twitch.mixco.js';
+
+require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+ })();
+
+ exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+ };
+
+ exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+ })(value.Value);
+
+ exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+ })(exports.Behaviour);
+
+ exports.call = factory(exports.Call);
+
+ exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+ })(exports.Behaviour);
+
+ exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+ })(exports.Output);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+ };
+
+ exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+ };
+
+ exports.switch_ = exports["switch"];
+
+ exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+ })(exports.Behaviour);
+
+ exports.mapIn = factory(exports.MapIn);
+
+ exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+ })(exports.Output);
+
+ exports.mapOut = factory(exports.MapOut);
+
+ exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+ })(multi(exports.MapIn, exports.MapOut));
+
+ exports.map = factory(exports.Map);
+
+ exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+ };
+
+ exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+ };
+
+ exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+ };
+
+ exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+ };
+
+ exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+ })(exports.Output);
+
+ exports.chooser = factory(exports.Chooser);
+
+ exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+ })(exports.Behaviour);
+
+ exports.when = factory(exports.When);
+
+ exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+ })(exports.Output);
+
+ exports.action = factory(exports.Action);
+
+ exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+ };
+
+ exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+ };
+
+ exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+ };
+
+ exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+ };
+
+ exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+ };
+
+ exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+ };
+
+ exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+ };
+
+}).call(this);
+
+},{"./transform":7,"./util":8,"./value":9,"events":10,"heterarchy":13,"underscore":16}],4:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var assert, exports, konsole;
+
+ assert = require('./util').assert;
+
+ konsole = this;
+
+ exports = konsole;
+
+ if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+ }
+
+ if (konsole.info == null) {
+ konsole.info = konsole.log;
+ }
+
+ if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+ }
+
+ if (konsole.error == null) {
+ konsole.error = konsole.log;
+ }
+
+ if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+ }
+
+ if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+ }
+
+ if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+ }
+
+ if (konsole.assert == null) {
+ konsole.assert = assert;
+ }
+
+}).call(this);
+
+},{"./util":8}],5:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+ multi = require('heterarchy').multi;
+
+ ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+ behaviour = require('./behaviour');
+
+ ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+ exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+ exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+ exports.MIDI_CC = MIDI_CC = 0xB;
+
+ exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+ midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+ };
+
+ exports.midiId = midiId;
+
+ pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+ };
+
+ noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+ };
+
+ noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+ };
+
+ ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+ };
+
+ exports.pbIds = pbIds;
+
+ exports.noteOnIds = noteOnIds;
+
+ exports.noteIds = noteIds;
+
+ exports.ccIds = ccIds;
+
+ exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+ };
+
+ exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+ })(behaviour.Actor);
+
+ exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+ })(exports.Control);
+
+ exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+ })(exports.Control);
+
+ exports.input = factory(exports.InControl);
+
+ exports.output = factory(exports.OutControl);
+
+ exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+ })(multi(exports.InControl, exports.OutControl));
+
+ exports.control = factory(exports.InOutControl);
+
+}).call(this);
+
+},{"./behaviour":3,"./util":8,"heterarchy":13,"underscore":16}],6:[function(require,module,exports){
+(function (process){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+ Control = require('./control').Control;
+
+ ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+ require('./console');
+
+ basename = require('path').basename;
+
+ S = require('string');
+
+ _ = require('underscore');
+
+ exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+ };
+
+ exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+ };
+
+ exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+ };
+
+ exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+ })();
+
+}).call(this);
+
+}).call(this,require('_process'))
+},{"./console":4,"./control":5,"./util":8,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],7:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+ exports.identity = function(v) {
+ return v;
+ };
+
+ exports.identity.inverse = exports.identity;
+
+ exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+ };
+
+ exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+
+ exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+ };
+
+ exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+ };
+
+ exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+ };
+
+ exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+ };
+
+ exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+ };
+
+ exports.identityT = identityT = exports.transformI(exports.identity);
+
+ exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+ exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+ exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+ };
+
+ exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+ };
+
+ exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+ exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+ };
+
+}).call(this);
+
+},{}],8:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+ };
+
+ Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+ };
+
+ Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+ };
+
+ Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+ };
+
+ exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+ };
+
+ exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+ };
+
+ exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+ };
+
+ exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+ };
+
+ exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+ };
+
+ exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+ };
+
+ exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+ };
+
+}).call(this);
+
+},{}],9:[function(require,module,exports){
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+ events = require('events');
+
+ util = require('./util');
+
+ factory = util.factory;
+
+ exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+ })(events.EventEmitter);
+
+ exports.value = factory(exports.Value);
+
+ exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+ })();
+
+ exports["const"] = factory(exports.Const);
+
+ exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+ })(exports.Value);
+
+ exports.reduce = factory(exports.Reduce);
+
+ exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+ };
+
+ exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+ })(exports.Value);
+
+ exports.transform = factory(exports.Transform);
+
+ exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+ };
+
+}).call(this);
+
+},{"./util":8,"events":10}],10:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+function EventEmitter() {
+ this._events = this._events || {};
+ this._maxListeners = this._maxListeners || undefined;
+}
+module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+EventEmitter.EventEmitter = EventEmitter;
+
+EventEmitter.prototype._events = undefined;
+EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!isNumber(n) || n < 0 || isNaN(n))
+ throw TypeError('n must be a positive number');
+ this._maxListeners = n;
+ return this;
+};
+
+EventEmitter.prototype.emit = function(type) {
+ var er, handler, len, args, i, listeners;
+
+ if (!this._events)
+ this._events = {};
+
+ // If there is no 'error' event listener then throw.
+ if (type === 'error') {
+ if (!this._events.error ||
+ (isObject(this._events.error) && !this._events.error.length)) {
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ }
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ }
+
+ handler = this._events[type];
+
+ if (isUndefined(handler))
+ return false;
+
+ if (isFunction(handler)) {
+ switch (arguments.length) {
+ // fast cases
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ // slower
+ default:
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+
+ listeners = handler.slice();
+ len = listeners.length;
+ for (i = 0; i < len; i++)
+ listeners[i].apply(this, args);
+ }
+
+ return true;
+};
+
+EventEmitter.prototype.addListener = function(type, listener) {
+ var m;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events)
+ this._events = {};
+
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (this._events.newListener)
+ this.emit('newListener', type,
+ isFunction(listener.listener) ?
+ listener.listener : listener);
+
+ if (!this._events[type])
+ // Optimize the case of one listener. Don't need the extra array object.
+ this._events[type] = listener;
+ else if (isObject(this._events[type]))
+ // If we've already got an array, just append.
+ this._events[type].push(listener);
+ else
+ // Adding the second element, need to change to array.
+ this._events[type] = [this._events[type], listener];
+
+ // Check for listener leak
+ if (isObject(this._events[type]) && !this._events[type].warned) {
+ var m;
+ if (!isUndefined(this._maxListeners)) {
+ m = this._maxListeners;
+ } else {
+ m = EventEmitter.defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ if (typeof console.trace === 'function') {
+ // not supported in IE 10
+ console.trace();
+ }
+ }
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ var fired = false;
+
+ function g() {
+ this.removeListener(type, g);
+
+ if (!fired) {
+ fired = true;
+ listener.apply(this, arguments);
+ }
+ }
+
+ g.listener = listener;
+ this.on(type, g);
+
+ return this;
+};
+
+// emits a 'removeListener' event iff the listener was removed
+EventEmitter.prototype.removeListener = function(type, listener) {
+ var list, position, length, i;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events || !this._events[type])
+ return this;
+
+ list = this._events[type];
+ length = list.length;
+ position = -1;
+
+ if (list === listener ||
+ (isFunction(list.listener) && list.listener === listener)) {
+ delete this._events[type];
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+
+ } else if (isObject(list)) {
+ for (i = length; i-- > 0;) {
+ if (list[i] === listener ||
+ (list[i].listener && list[i].listener === listener)) {
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (list.length === 1) {
+ list.length = 0;
+ delete this._events[type];
+ } else {
+ list.splice(position, 1);
+ }
+
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ var key, listeners;
+
+ if (!this._events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!this._events.removeListener) {
+ if (arguments.length === 0)
+ this._events = {};
+ else if (this._events[type])
+ delete this._events[type];
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ for (key in this._events) {
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = {};
+ return this;
+ }
+
+ listeners = this._events[type];
+
+ if (isFunction(listeners)) {
+ this.removeListener(type, listeners);
+ } else {
+ // LIFO order
+ while (listeners.length)
+ this.removeListener(type, listeners[listeners.length - 1]);
+ }
+ delete this._events[type];
+
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ var ret;
+ if (!this._events || !this._events[type])
+ ret = [];
+ else if (isFunction(this._events[type]))
+ ret = [this._events[type]];
+ else
+ ret = this._events[type].slice();
+ return ret;
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ var ret;
+ if (!emitter._events || !emitter._events[type])
+ ret = 0;
+ else if (isFunction(emitter._events[type]))
+ ret = 1;
+ else
+ ret = emitter._events[type].length;
+ return ret;
+};
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+
+},{}],11:[function(require,module,exports){
+(function (process){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// resolves . and .. elements in a path array with directory names there
+// must be no slashes, empty elements, or device names (c:\) in the array
+// (so also no leading and trailing slashes - it does not distinguish
+// relative and absolute paths)
+function normalizeArray(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up--; up) {
+ parts.unshift('..');
+ }
+ }
+
+ return parts;
+}
+
+// Split a filename into [root, dir, basename, ext], unix version
+// 'root' is just a slash, or nothing.
+var splitPathRe =
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+var splitPath = function(filename) {
+ return splitPathRe.exec(filename).slice(1);
+};
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+};
+
+// path.normalize(path)
+// posix version
+exports.normalize = function(path) {
+ var isAbsolute = exports.isAbsolute(path),
+ trailingSlash = substr(path, -1) === '/';
+
+ // Normalize the path
+ path = normalizeArray(filter(path.split('/'), function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+
+ return (isAbsolute ? '/' : '') + path;
+};
+
+// posix version
+exports.isAbsolute = function(path) {
+ return path.charAt(0) === '/';
+};
+
+// posix version
+exports.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ if (typeof p !== 'string') {
+ throw new TypeError('Arguments to path.join must be strings');
+ }
+ return p;
+ }).join('/'));
+};
+
+
+// path.relative(from, to)
+// posix version
+exports.relative = function(from, to) {
+ from = exports.resolve(from).substr(1);
+ to = exports.resolve(to).substr(1);
+
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+
+ return outputParts.join('/');
+};
+
+exports.sep = '/';
+exports.delimiter = ':';
+
+exports.dirname = function(path) {
+ var result = splitPath(path),
+ root = result[0],
+ dir = result[1];
+
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+
+ return root + dir;
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPath(path)[2];
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPath(path)[3];
+};
+
+function filter (xs, f) {
+ if (xs.filter) return xs.filter(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (f(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// String.prototype.substr - negative index don't work in IE8
+var substr = 'ab'.substr(-1) === 'b'
+ ? function (str, start, len) { return str.substr(start, len) }
+ : function (str, start, len) {
+ if (start < 0) start = str.length + start;
+ return str.substr(start, len);
+ }
+;
+
+}).call(this,require('_process'))
+},{"_process":12}],12:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],13:[function(require,module,exports){
+// Generated by CoffeeScript 1.9.3
+(function() {
+ var assert, copyOwn, every, find, generate, head, hierarchy, inherited, isEmpty, isEqual, isJavaScriptClass, map, memoize, merge, mro, partial, ref, reject, reparent, some, tail, without,
+ slice = [].slice,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ ref = require('underscore'), head = ref.head, tail = ref.tail, map = ref.map, find = ref.find, some = ref.some, without = ref.without, isEmpty = ref.isEmpty, every = ref.every, memoize = ref.memoize, reject = ref.reject, partial = ref.partial, isEqual = ref.isEqual;
+
+ assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+ };
+
+ exports.multi = function() {
+ var bases;
+ bases = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return generate(merge(map(bases, mro).concat([bases])));
+ };
+
+ generate = memoize(function(linearization) {
+ var next, result;
+ next = head(linearization);
+ if (isEqual(linearization, hierarchy(next))) {
+ return next;
+ } else {
+ return result = (function(superClass) {
+ var class1;
+
+ extend(result, superClass);
+
+ function result() {
+ return class1.apply(this, arguments);
+ }
+
+ result.prototype.__mro__ = linearization;
+
+ class1 = reparent(next, result, next.prototype.constructor);
+
+ copyOwn(next, result);
+
+ copyOwn(next.prototype, result.prototype, partial(reparent, next, result));
+
+ return result;
+
+ })(generate(tail(linearization)));
+ }
+ });
+
+ copyOwn = function(from, to, project) {
+ var key, value;
+ if (project == null) {
+ project = function(x) {
+ return x;
+ };
+ }
+ for (key in from) {
+ if (!hasProp.call(from, key)) continue;
+ value = from[key];
+ if (!to.hasOwnProperty(key)) {
+ to[key] = project(value);
+ }
+ }
+ return to;
+ };
+
+ reparent = function(oldklass, newklass, value) {
+ var newsuper, oldsuper, superctor;
+ if (!(value instanceof Function)) {
+ return value;
+ } else if (value === oldklass.prototype.constructor && inherited(oldklass) === Object) {
+ superctor = inherited(newklass).prototype.constructor;
+ return function() {
+ superctor.apply(this, arguments);
+ return value.apply(this, arguments);
+ };
+ } else {
+ newsuper = inherited(newklass).prototype;
+ oldsuper = oldklass.__super__;
+ return function() {
+ oldklass.__super__ = newsuper;
+ try {
+ return value.apply(this, arguments);
+ } finally {
+ oldklass.__super__ = oldsuper;
+ }
+ };
+ }
+ };
+
+ merge = function(inputs) {
+ var next, results;
+ results = [];
+ while (!isEmpty(inputs)) {
+ next = find(map(inputs, head), function(candidate) {
+ return every(inputs, function(input) {
+ return indexOf.call(tail(input), candidate) < 0;
+ });
+ });
+ assert(next != null, "Inconsistent multiple inheritance");
+ inputs = reject(map(inputs, function(lst) {
+ return without(lst, next);
+ }), isEmpty);
+ results.push(next);
+ }
+ return results;
+ };
+
+ isJavaScriptClass = function(cls) {
+ return cls === Array || cls === Boolean || cls === Date || cls === Error || cls === Function || cls === Number || cls === RegExp || cls === String || cls === Object;
+ };
+
+ exports.mro = mro = function(cls) {
+ var result;
+ if ((cls == null) || (cls.prototype == null)) {
+ return [];
+ } else if (!cls.prototype.hasOwnProperty('__mro__')) {
+ result = [cls].concat(mro(inherited(cls)));
+ if (!isJavaScriptClass(cls)) {
+ cls.prototype.__mro__ = result;
+ }
+ return result;
+ } else {
+ return cls.prototype.__mro__;
+ }
+ };
+
+ exports.inherited = inherited = function(cls) {
+ var ref1;
+ return (ref1 = Object.getPrototypeOf(cls.prototype)) != null ? ref1.constructor : void 0;
+ };
+
+ exports.hierarchy = hierarchy = function(cls) {
+ if (cls == null) {
+ return [];
+ } else {
+ return [cls].concat(hierarchy(inherited(cls)));
+ }
+ };
+
+ exports.isinstance = function() {
+ var classes, obj;
+ obj = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.issubclass.apply(exports, [obj != null ? obj.constructor : void 0].concat(slice.call(classes)));
+ };
+
+ exports.issubclass = function() {
+ var classes, klass, linearization;
+ klass = arguments[0], classes = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ linearization = mro(klass);
+ return some(classes, function(cls) {
+ return indexOf.call(linearization, cls) >= 0;
+ });
+ };
+
+}).call(this);
+
+},{"underscore":16}],14:[function(require,module,exports){
+function count(self, substr) {
+ var count = 0
+ var pos = self.indexOf(substr)
+
+ while (pos >= 0) {
+ count += 1
+ pos = self.indexOf(substr, pos + 1)
+ }
+
+ return count
+}
+
+module.exports = count
+},{}],15:[function(require,module,exports){
+/*
+string.js - Copyright (C) 2012-2014, JP Richardson
+*/
+
+!(function() {
+ "use strict";
+
+ var VERSION = '3.1.3';
+
+ var ENTITIES = {};
+
+ // from http://semplicewebsites.com/removing-accents-javascript
+ var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};
+
+//******************************************************************************
+// Added an initialize function which is essentially the code from the S
+// constructor. Now, the S constructor calls this and a new method named
+// setValue calls it as well. The setValue function allows constructors for
+// modules that extend string.js to set the initial value of an object without
+// knowing the internal workings of string.js.
+//
+// Also, all methods which return a new S object now call:
+//
+// return new this.constructor(s);
+//
+// instead of:
+//
+// return new S(s);
+//
+// This allows extended objects to keep their proper instanceOf and constructor.
+//******************************************************************************
+
+ function initialize (object, s) {
+ if (s !== null && s !== undefined) {
+ if (typeof s === 'string')
+ object.s = s;
+ else
+ object.s = s.toString();
+ } else {
+ object.s = s; //null or undefined
+ }
+
+ object.orig = s; //original object, currently only used by toCSV() and toBoolean()
+
+ if (s !== null && s !== undefined) {
+ if (object.__defineGetter__) {
+ object.__defineGetter__('length', function() {
+ return object.s.length;
+ })
+ } else {
+ object.length = s.length;
+ }
+ } else {
+ object.length = -1;
+ }
+ }
+
+ function S(s) {
+ initialize(this, s);
+ }
+
+ var __nsp = String.prototype;
+ var __sp = S.prototype = {
+
+ between: function(left, right) {
+ var s = this.s;
+ var startPos = s.indexOf(left);
+ var endPos = s.indexOf(right, startPos + left.length);
+ if (endPos == -1 && right != null)
+ return new this.constructor('')
+ else if (endPos == -1 && right == null)
+ return new this.constructor(s.substring(startPos + left.length))
+ else
+ return new this.constructor(s.slice(startPos + left.length, endPos));
+ },
+
+ //# modified slightly from https://github.com/epeli/underscore.string
+ camelize: function() {
+ var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) {
+ return (c ? c.toUpperCase() : '');
+ });
+ return new this.constructor(s);
+ },
+
+ capitalize: function() {
+ return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase());
+ },
+
+ charAt: function(index) {
+ return this.s.charAt(index);
+ },
+
+ chompLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ s = s.slice(prefix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ chompRight: function(suffix) {
+ if (this.endsWith(suffix)) {
+ var s = this.s;
+ s = s.slice(0, s.length - suffix.length);
+ return new this.constructor(s);
+ } else {
+ return this;
+ }
+ },
+
+ //#thanks Google
+ collapseWhitespace: function() {
+ var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, '');
+ return new this.constructor(s);
+ },
+
+ contains: function(ss) {
+ return this.s.indexOf(ss) >= 0;
+ },
+
+ count: function(ss) {
+ return require('./_count')(this.s, ss)
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ dasherize: function() {
+ var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ latinise: function() {
+ var s = this.replace(/[^A-Za-z0-9\[\] ]/g, function(x) { return latin_map[x] || x; });
+ return new this.constructor(s);
+ },
+
+ decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js
+ var s = this.s;
+ s = s.replace(/(\d+);?/g, function (_, code) {
+ return String.fromCharCode(code);
+ })
+ .replace(/[xX]([A-Fa-f0-9]+);?/g, function (_, hex) {
+ return String.fromCharCode(parseInt(hex, 16));
+ })
+ .replace(/&([^;\W]+;?)/g, function (m, e) {
+ var ee = e.replace(/;$/, '');
+ var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]);
+
+ if (typeof target === 'number') {
+ return String.fromCharCode(target);
+ }
+ else if (typeof target === 'string') {
+ return target;
+ }
+ else {
+ return m;
+ }
+ })
+
+ return new this.constructor(s);
+ },
+
+ endsWith: function() {
+ var suffixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < suffixes.length; ++i) {
+ var l = this.s.length - suffixes[i].length;
+ if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true;
+ }
+ return false;
+ },
+
+ escapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
+ },
+
+ ensureLeft: function(prefix) {
+ var s = this.s;
+ if (s.indexOf(prefix) === 0) {
+ return this;
+ } else {
+ return new this.constructor(prefix + s);
+ }
+ },
+
+ ensureRight: function(suffix) {
+ var s = this.s;
+ if (this.endsWith(suffix)) {
+ return this;
+ } else {
+ return new this.constructor(s + suffix);
+ }
+ },
+
+ humanize: function() { //modified from underscore.string
+ if (this.s === null || this.s === undefined)
+ return new this.constructor('')
+ var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize()
+ return new this.constructor(s)
+ },
+
+ isAlpha: function() {
+ return !/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase());
+ },
+
+ isAlphaNumeric: function() {
+ return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase());
+ },
+
+ isEmpty: function() {
+ return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s);
+ },
+
+ isLower: function() {
+ return this.isAlpha() && this.s.toLowerCase() === this.s;
+ },
+
+ isNumeric: function() {
+ return !/[^0-9]/.test(this.s);
+ },
+
+ isUpper: function() {
+ return this.isAlpha() && this.s.toUpperCase() === this.s;
+ },
+
+ left: function(N) {
+ if (N >= 0) {
+ var s = this.s.substr(0, N);
+ return new this.constructor(s);
+ } else {
+ return this.right(-N);
+ }
+ },
+
+ lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines
+ return this.replaceAll('\r\n', '\n').s.split('\n');
+ },
+
+ pad: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ len = len - this.s.length;
+ var left = Array(Math.ceil(len / 2) + 1).join(ch);
+ var right = Array(Math.floor(len / 2) + 1).join(ch);
+ return new this.constructor(left + this.s + right);
+ },
+
+ padLeft: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s);
+ },
+
+ padRight: function(len, ch) { //https://github.com/component/pad
+ if (ch == null) ch = ' ';
+ if (this.s.length >= len) return new this.constructor(this.s);
+ return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch));
+ },
+
+ parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what
+ delimiter = delimiter || ',';
+ escape = escape || '\\'
+ if (typeof qualifier == 'undefined')
+ qualifier = '"';
+
+ var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this;
+ var ca = function(i){return self.s.charAt(i)};
+ if (typeof lineDelimiter !== 'undefined') var rows = [];
+
+ if (!qualifier)
+ inField = true;
+
+ while (i < len) {
+ var current = ca(i);
+ switch (current) {
+ case escape:
+ //fix for issues #32 and #35
+ if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) {
+ i += 1;
+ fieldBuffer.push(ca(i));
+ break;
+ }
+ if (escape !== qualifier) break;
+ case qualifier:
+ inField = !inField;
+ break;
+ case delimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ }
+ if (inField && qualifier)
+ fieldBuffer.push(current);
+ else {
+ fields.push(fieldBuffer.join(''))
+ fieldBuffer.length = 0;
+ }
+ break;
+ case lineDelimiter:
+ if(inUnqualifiedString) {
+ inField=false;
+ inUnqualifiedString=false;
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ else if (inField) {
+ fieldBuffer.push(current);
+ } else {
+ if (rows) {
+ fields.push(fieldBuffer.join(''))
+ rows.push(fields);
+ fields = [];
+ fieldBuffer.length = 0;
+ }
+ }
+ break;
+ case ' ':
+ if (inField)
+ fieldBuffer.push(current);
+ break;
+ default:
+ if (inField)
+ fieldBuffer.push(current);
+ else if(current!==qualifier) {
+ fieldBuffer.push(current);
+ inField=true;
+ inUnqualifiedString=true;
+ }
+ break;
+ }
+ i += 1;
+ }
+
+ fields.push(fieldBuffer.join(''));
+ if (rows) {
+ rows.push(fields);
+ return rows;
+ }
+ return fields;
+ },
+
+ replaceAll: function(ss, r) {
+ //var s = this.s.replace(new RegExp(ss, 'g'), r);
+ var s = this.s.split(ss).join(r)
+ return new this.constructor(s);
+ },
+
+ strip: function() {
+ var ss = this.s;
+ for(var i= 0, n=arguments.length; i= 0) {
+ var s = this.s.substr(this.s.length - N, N);
+ return new this.constructor(s);
+ } else {
+ return this.left(-N);
+ }
+ },
+
+ setValue: function (s) {
+ initialize(this, s);
+ return this;
+ },
+
+ slugify: function() {
+ var sl = (new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s;
+ if (sl.charAt(0) === '-')
+ sl = sl.substr(1);
+ return new this.constructor(sl);
+ },
+
+ startsWith: function() {
+ var prefixes = Array.prototype.slice.call(arguments, 0);
+ for (var i = 0; i < prefixes.length; ++i) {
+ if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true;
+ }
+ return false;
+ },
+
+ stripPunctuation: function() {
+ //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
+ return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
+ },
+
+ stripTags: function() { //from sugar.js
+ var s = this.s, args = arguments.length > 0 ? arguments : [''];
+ multiArgs(args, function(tag) {
+ s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), '');
+ });
+ return new this.constructor(s);
+ },
+
+ template: function(values, opening, closing) {
+ var s = this.s
+ var opening = opening || Export.TMPL_OPEN
+ var closing = closing || Export.TMPL_CLOSE
+
+ var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
+ var r = new RegExp(open + '(.+?)' + close, 'g')
+ //, r = /\{\{(.+?)\}\}/g
+ var matches = s.match(r) || [];
+
+ matches.forEach(function(match) {
+ var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }}
+ var value = typeof values[key] == 'undefined' ? '' : values[key];
+ s = s.replace(match, value);
+ });
+ return new this.constructor(s);
+ },
+
+ times: function(n) {
+ return new this.constructor(new Array(n + 1).join(this.s));
+ },
+
+ toBoolean: function() {
+ if (typeof this.orig === 'string') {
+ var s = this.s.toLowerCase();
+ return s === 'true' || s === 'yes' || s === 'on' || s === '1';
+ } else
+ return this.orig === true || this.orig === 1;
+ },
+
+ toFloat: function(precision) {
+ var num = parseFloat(this.s)
+ if (precision)
+ return parseFloat(num.toFixed(precision))
+ else
+ return num
+ },
+
+ toInt: function() { //thanks Google
+ // If the string starts with '0x' or '-0x', parse as hex.
+ return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10)
+ },
+
+ trim: function() {
+ var s;
+ if (typeof __nsp.trim === 'undefined')
+ s = this.s.replace(/(^\s*|\s*$)/g, '')
+ else
+ s = this.s.trim()
+ return new this.constructor(s);
+ },
+
+ trimLeft: function() {
+ var s;
+ if (__nsp.trimLeft)
+ s = this.s.trimLeft();
+ else
+ s = this.s.replace(/(^\s*)/g, '');
+ return new this.constructor(s);
+ },
+
+ trimRight: function() {
+ var s;
+ if (__nsp.trimRight)
+ s = this.s.trimRight();
+ else
+ s = this.s.replace(/\s+$/, '');
+ return new this.constructor(s);
+ },
+
+ truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz
+ var str = this.s;
+
+ length = ~~length;
+ pruneStr = pruneStr || '...';
+
+ if (str.length <= length) return new this.constructor(str);
+
+ var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
+ template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
+
+ if (template.slice(template.length-2).match(/\w\w/))
+ template = template.replace(/\s*\S+$/, '');
+ else
+ template = new S(template.slice(0, template.length-1)).trimRight().s;
+
+ return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr);
+ },
+
+ toCSV: function() {
+ var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false;
+ var dataArray = [];
+
+ function hasVal(it) {
+ return it !== null && it !== '';
+ }
+
+ if (typeof arguments[0] === 'object') {
+ delim = arguments[0].delimiter || delim;
+ delim = arguments[0].separator || delim;
+ qualifier = arguments[0].qualifier || qualifier;
+ encloseNumbers = !!arguments[0].encloseNumbers;
+ escape = arguments[0].escape || escape;
+ keys = !!arguments[0].keys;
+ } else if (typeof arguments[0] === 'string') {
+ delim = arguments[0];
+ }
+
+ if (typeof arguments[1] === 'string')
+ qualifier = arguments[1];
+
+ if (arguments[1] === null)
+ qualifier = null;
+
+ if (this.orig instanceof Array)
+ dataArray = this.orig;
+ else { //object
+ for (var key in this.orig)
+ if (this.orig.hasOwnProperty(key))
+ if (keys)
+ dataArray.push(key);
+ else
+ dataArray.push(this.orig[key]);
+ }
+
+ var rep = escape + qualifier;
+ var buildString = [];
+ for (var i = 0; i < dataArray.length; ++i) {
+ var shouldQualify = hasVal(qualifier)
+ if (typeof dataArray[i] == 'number')
+ shouldQualify &= encloseNumbers;
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (dataArray[i] !== null && dataArray[i] !== undefined) {
+ var d = new S(dataArray[i]).replaceAll(qualifier, rep).s;
+ buildString.push(d);
+ } else
+ buildString.push('')
+
+ if (shouldQualify)
+ buildString.push(qualifier);
+
+ if (delim)
+ buildString.push(delim);
+ }
+
+ //chop last delim
+ //console.log(buildString.length)
+ buildString.length = buildString.length - 1;
+ return new this.constructor(buildString.join(''));
+ },
+
+ toString: function() {
+ return this.s;
+ },
+
+ //#modified from https://github.com/epeli/underscore.string
+ underscore: function() {
+ var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/([A-Z\d]+)([A-Z][a-z])/,'$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
+ return new this.constructor(s);
+ },
+
+ unescapeHTML: function() { //from underscore.string
+ return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){
+ var match;
+
+ if (entityCode in escapeChars) {
+ return escapeChars[entityCode];
+ } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
+ return String.fromCharCode(parseInt(match[1], 16));
+ } else if (match = entityCode.match(/^#(\d+)$/)) {
+ return String.fromCharCode(~~match[1]);
+ } else {
+ return entity;
+ }
+ }));
+ },
+
+ valueOf: function() {
+ return this.s.valueOf();
+ },
+
+ //#Added a New Function called wrapHTML.
+ wrapHTML: function (tagName, tagAttrs) {
+ var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = '';
+ if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"';
+ s = wrapped.concat('<', el, elAttr, '>', this, '', el, '>');
+ return new this.constructor(s);
+ }
+ }
+
+ var methodsAdded = [];
+ function extendPrototype() {
+ for (var name in __sp) {
+ (function(name){
+ var func = __sp[name];
+ if (!__nsp.hasOwnProperty(name)) {
+ methodsAdded.push(name);
+ __nsp[name] = function() {
+ String.prototype.s = this;
+ return func.apply(this, arguments);
+ }
+ }
+ })(name);
+ }
+ }
+
+ function restorePrototype() {
+ for (var i = 0; i < methodsAdded.length; ++i)
+ delete String.prototype[methodsAdded[i]];
+ methodsAdded.length = 0;
+ }
+
+
+/*************************************
+/* Attach Native JavaScript String Properties
+/*************************************/
+
+ var nativeProperties = getNativeStringProperties();
+ for (var name in nativeProperties) {
+ (function(name) {
+ var stringProp = __nsp[name];
+ if (typeof stringProp == 'function') {
+ //console.log(stringProp)
+ if (!__sp[name]) {
+ if (nativeProperties[name] === 'string') {
+ __sp[name] = function() {
+ //console.log(name)
+ return new this.constructor(stringProp.apply(this, arguments));
+ }
+ } else {
+ __sp[name] = stringProp;
+ }
+ }
+ }
+ })(name);
+ }
+
+
+/*************************************
+/* Function Aliases
+/*************************************/
+
+ __sp.repeat = __sp.times;
+ __sp.include = __sp.contains;
+ __sp.toInteger = __sp.toInt;
+ __sp.toBool = __sp.toBoolean;
+ __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML'
+
+
+//******************************************************************************
+// Set the constructor. Without this, string.js objects are instances of
+// Object instead of S.
+//******************************************************************************
+
+ __sp.constructor = S;
+
+
+/*************************************
+/* Private Functions
+/*************************************/
+
+ function getNativeStringProperties() {
+ var names = getNativeStringPropertyNames();
+ var retObj = {};
+
+ for (var i = 0; i < names.length; ++i) {
+ var name = names[i];
+ var func = __nsp[name];
+ try {
+ // #127: pass extra parameter to keep shelljs happy
+ var type = typeof func.apply('test', ['string']);
+ retObj[name] = type;
+ } catch (e) {}
+ }
+ return retObj;
+ }
+
+ function getNativeStringPropertyNames() {
+ var results = [];
+ if (Object.getOwnPropertyNames) {
+ results = Object.getOwnPropertyNames(__nsp);
+ results.splice(results.indexOf('valueOf'), 1);
+ results.splice(results.indexOf('toString'), 1);
+ return results;
+ } else { //meant for legacy cruft, this could probably be made more efficient
+ var stringNames = {};
+ var objectNames = [];
+ for (var name in String.prototype)
+ stringNames[name] = name;
+
+ for (var name in Object.prototype)
+ delete stringNames[name];
+
+ //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names
+ for (var name in stringNames) {
+ results.push(name);
+ }
+ return results;
+ }
+ }
+
+ function Export(str) {
+ return new S(str);
+ };
+
+ //attach exports to StringJSWrapper
+ Export.extendPrototype = extendPrototype;
+ Export.restorePrototype = restorePrototype;
+ Export.VERSION = VERSION;
+ Export.TMPL_OPEN = '{{';
+ Export.TMPL_CLOSE = '}}';
+ Export.ENTITIES = ENTITIES;
+
+
+
+/*************************************
+/* Exports
+/*************************************/
+
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
+ module.exports = Export;
+
+ } else {
+
+ if(typeof define === "function" && define.amd) {
+ define([], function() {
+ return Export;
+ });
+ } else {
+ window.S = Export;
+ }
+ }
+
+
+/*************************************
+/* 3rd Party Private Functions
+/*************************************/
+
+ //from sugar.js
+ function multiArgs(args, fn) {
+ var result = [], i;
+ for(i = 0; i < args.length; i++) {
+ result.push(args[i]);
+ if(fn) fn.call(args, args[i], i);
+ }
+ return result;
+ }
+
+ //from underscore.string
+ var escapeChars = {
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ apos: "'",
+ amp: '&'
+ };
+
+ function escapeRegExp (s) {
+ // most part from https://github.com/skulpt/skulpt/blob/ecaf75e69c2e539eff124b2ab45df0b01eaf2295/src/str.js#L242
+ var c;
+ var i;
+ var ret = [];
+ var re = /^[A-Za-z0-9]+$/;
+ s = ensureString(s);
+ for (i = 0; i < s.length; ++i) {
+ c = s.charAt(i);
+
+ if (re.test(c)) {
+ ret.push(c);
+ }
+ else {
+ if (c === "\\000") {
+ ret.push("\\000");
+ }
+ else {
+ ret.push("\\" + c);
+ }
+ }
+ }
+ return ret.join("");
+ }
+
+ function ensureString(string) {
+ return string == null ? '' : '' + string;
+ }
+
+ //from underscore.string
+ var reversedEscapeChars = {};
+ for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
+
+ ENTITIES = {
+ "amp" : "&",
+ "gt" : ">",
+ "lt" : "<",
+ "quot" : "\"",
+ "apos" : "'",
+ "AElig" : 198,
+ "Aacute" : 193,
+ "Acirc" : 194,
+ "Agrave" : 192,
+ "Aring" : 197,
+ "Atilde" : 195,
+ "Auml" : 196,
+ "Ccedil" : 199,
+ "ETH" : 208,
+ "Eacute" : 201,
+ "Ecirc" : 202,
+ "Egrave" : 200,
+ "Euml" : 203,
+ "Iacute" : 205,
+ "Icirc" : 206,
+ "Igrave" : 204,
+ "Iuml" : 207,
+ "Ntilde" : 209,
+ "Oacute" : 211,
+ "Ocirc" : 212,
+ "Ograve" : 210,
+ "Oslash" : 216,
+ "Otilde" : 213,
+ "Ouml" : 214,
+ "THORN" : 222,
+ "Uacute" : 218,
+ "Ucirc" : 219,
+ "Ugrave" : 217,
+ "Uuml" : 220,
+ "Yacute" : 221,
+ "aacute" : 225,
+ "acirc" : 226,
+ "aelig" : 230,
+ "agrave" : 224,
+ "aring" : 229,
+ "atilde" : 227,
+ "auml" : 228,
+ "ccedil" : 231,
+ "eacute" : 233,
+ "ecirc" : 234,
+ "egrave" : 232,
+ "eth" : 240,
+ "euml" : 235,
+ "iacute" : 237,
+ "icirc" : 238,
+ "igrave" : 236,
+ "iuml" : 239,
+ "ntilde" : 241,
+ "oacute" : 243,
+ "ocirc" : 244,
+ "ograve" : 242,
+ "oslash" : 248,
+ "otilde" : 245,
+ "ouml" : 246,
+ "szlig" : 223,
+ "thorn" : 254,
+ "uacute" : 250,
+ "ucirc" : 251,
+ "ugrave" : 249,
+ "uuml" : 252,
+ "yacute" : 253,
+ "yuml" : 255,
+ "copy" : 169,
+ "reg" : 174,
+ "nbsp" : 160,
+ "iexcl" : 161,
+ "cent" : 162,
+ "pound" : 163,
+ "curren" : 164,
+ "yen" : 165,
+ "brvbar" : 166,
+ "sect" : 167,
+ "uml" : 168,
+ "ordf" : 170,
+ "laquo" : 171,
+ "not" : 172,
+ "shy" : 173,
+ "macr" : 175,
+ "deg" : 176,
+ "plusmn" : 177,
+ "sup1" : 185,
+ "sup2" : 178,
+ "sup3" : 179,
+ "acute" : 180,
+ "micro" : 181,
+ "para" : 182,
+ "middot" : 183,
+ "cedil" : 184,
+ "ordm" : 186,
+ "raquo" : 187,
+ "frac14" : 188,
+ "frac12" : 189,
+ "frac34" : 190,
+ "iquest" : 191,
+ "times" : 215,
+ "divide" : 247,
+ "OElig;" : 338,
+ "oelig;" : 339,
+ "Scaron;" : 352,
+ "scaron;" : 353,
+ "Yuml;" : 376,
+ "fnof;" : 402,
+ "circ;" : 710,
+ "tilde;" : 732,
+ "Alpha;" : 913,
+ "Beta;" : 914,
+ "Gamma;" : 915,
+ "Delta;" : 916,
+ "Epsilon;" : 917,
+ "Zeta;" : 918,
+ "Eta;" : 919,
+ "Theta;" : 920,
+ "Iota;" : 921,
+ "Kappa;" : 922,
+ "Lambda;" : 923,
+ "Mu;" : 924,
+ "Nu;" : 925,
+ "Xi;" : 926,
+ "Omicron;" : 927,
+ "Pi;" : 928,
+ "Rho;" : 929,
+ "Sigma;" : 931,
+ "Tau;" : 932,
+ "Upsilon;" : 933,
+ "Phi;" : 934,
+ "Chi;" : 935,
+ "Psi;" : 936,
+ "Omega;" : 937,
+ "alpha;" : 945,
+ "beta;" : 946,
+ "gamma;" : 947,
+ "delta;" : 948,
+ "epsilon;" : 949,
+ "zeta;" : 950,
+ "eta;" : 951,
+ "theta;" : 952,
+ "iota;" : 953,
+ "kappa;" : 954,
+ "lambda;" : 955,
+ "mu;" : 956,
+ "nu;" : 957,
+ "xi;" : 958,
+ "omicron;" : 959,
+ "pi;" : 960,
+ "rho;" : 961,
+ "sigmaf;" : 962,
+ "sigma;" : 963,
+ "tau;" : 964,
+ "upsilon;" : 965,
+ "phi;" : 966,
+ "chi;" : 967,
+ "psi;" : 968,
+ "omega;" : 969,
+ "thetasym;" : 977,
+ "upsih;" : 978,
+ "piv;" : 982,
+ "ensp;" : 8194,
+ "emsp;" : 8195,
+ "thinsp;" : 8201,
+ "zwnj;" : 8204,
+ "zwj;" : 8205,
+ "lrm;" : 8206,
+ "rlm;" : 8207,
+ "ndash;" : 8211,
+ "mdash;" : 8212,
+ "lsquo;" : 8216,
+ "rsquo;" : 8217,
+ "sbquo;" : 8218,
+ "ldquo;" : 8220,
+ "rdquo;" : 8221,
+ "bdquo;" : 8222,
+ "dagger;" : 8224,
+ "Dagger;" : 8225,
+ "bull;" : 8226,
+ "hellip;" : 8230,
+ "permil;" : 8240,
+ "prime;" : 8242,
+ "Prime;" : 8243,
+ "lsaquo;" : 8249,
+ "rsaquo;" : 8250,
+ "oline;" : 8254,
+ "frasl;" : 8260,
+ "euro;" : 8364,
+ "image;" : 8465,
+ "weierp;" : 8472,
+ "real;" : 8476,
+ "trade;" : 8482,
+ "alefsym;" : 8501,
+ "larr;" : 8592,
+ "uarr;" : 8593,
+ "rarr;" : 8594,
+ "darr;" : 8595,
+ "harr;" : 8596,
+ "crarr;" : 8629,
+ "lArr;" : 8656,
+ "uArr;" : 8657,
+ "rArr;" : 8658,
+ "dArr;" : 8659,
+ "hArr;" : 8660,
+ "forall;" : 8704,
+ "part;" : 8706,
+ "exist;" : 8707,
+ "empty;" : 8709,
+ "nabla;" : 8711,
+ "isin;" : 8712,
+ "notin;" : 8713,
+ "ni;" : 8715,
+ "prod;" : 8719,
+ "sum;" : 8721,
+ "minus;" : 8722,
+ "lowast;" : 8727,
+ "radic;" : 8730,
+ "prop;" : 8733,
+ "infin;" : 8734,
+ "ang;" : 8736,
+ "and;" : 8743,
+ "or;" : 8744,
+ "cap;" : 8745,
+ "cup;" : 8746,
+ "int;" : 8747,
+ "there4;" : 8756,
+ "sim;" : 8764,
+ "cong;" : 8773,
+ "asymp;" : 8776,
+ "ne;" : 8800,
+ "equiv;" : 8801,
+ "le;" : 8804,
+ "ge;" : 8805,
+ "sub;" : 8834,
+ "sup;" : 8835,
+ "nsub;" : 8836,
+ "sube;" : 8838,
+ "supe;" : 8839,
+ "oplus;" : 8853,
+ "otimes;" : 8855,
+ "perp;" : 8869,
+ "sdot;" : 8901,
+ "lceil;" : 8968,
+ "rceil;" : 8969,
+ "lfloor;" : 8970,
+ "rfloor;" : 8971,
+ "lang;" : 9001,
+ "rang;" : 9002,
+ "loz;" : 9674,
+ "spades;" : 9824,
+ "clubs;" : 9827,
+ "hearts;" : 9829,
+ "diams;" : 9830
+ }
+
+
+}).call(this);
+
+},{"./_count":14}],16:[function(require,module,exports){
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
+
+},{}],"/home/raskolnikov/dev/mixco/script/novation_twitch.mixco":[function(require,module,exports){
+// script.twitch
+// =============
+//
+// > This file is part of the [Mixco framework](http://sinusoid.es/mixco).
+// > - **View me [on a static web](http://sinusoid.es/mixco/script/novation_twitch.mixco.html)**
+// > - **View me [on GitHub](https://github.com/arximboldi/mixco/blob/master/script/novation_twitch.mixco.litcoffee)**
+//
+// Mixx script file for the **Novation Twitch** controller.
+//
+// This script serves as **tutorial** for creating scripts using the
+// *Mixco* framework, but programming directly in JavaScript. Still,
+// we recommend you to try CoffeeScript, since it is a bit of a nicer
+// language.
+//
+// If you want to modify this script, you may want to read the
+// [Novation Twitch Programmer Guide](https://us.novationmusic.com/support/downloads/twitch-programmers-reference-guide)
+//
+// ### Note for Linux Users
+//
+// The Linux Kernel version 3.10 is required to get Novation Twitch
+// detected as soundcard or MIDI device.
+//
+// 
+//
+// Dependencies
+// ------------
+//
+// First, we have to import the modules from the framework. We use
+// that the *NodeJS* `require` function. Note that all other NodeJS
+// modules are usable too when writing your script with the *Mixco*
+// framework.
+
+var _ = require('underscore')
+var mixco = require('mixco')
+var c = mixco.control
+var b = mixco.behaviour
+var v = mixco.value
+
+// The script
+// ----------
+//
+// When writing a controller script we use the `script.register`
+// function to generate and install a script instance in the current
+// module. The first parameter is the current module as defined by
+// *NodeJS*, the second parameter is the JavaScript object with all
+// the functions and information about our script.
+
+mixco.script.register(module, {
+
+ // ### Metadata
+ //
+ // Then the `info` object contains the meta-data that is displayed
+ // to the user in the MIDI mapping chooser of Mixxx.
+
+ info: {
+ name: "[mixco] Novation Twitch",
+ author: "Juan Pedro Bolivar Puente ",
+ forums: 'https://github.com/arximboldi/mixco/issues',
+ wiki: 'https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html',
+ description: "Controller mapping for Novation Twitch (in basic mode).",
+ },
+
+ // ### Constructor
+ //
+ // The constructor contains the definition of the MIDI mapping.
+ // Here we create all the different control objects and add them
+ // to the script instance.
+
+ constructor: function () {
+
+ // #### Master section
+ //
+ // Many of the master controls of the that the *pre-hear
+ // volume*, *pre-hear mix*, *booth volume* and *master volume*
+ // knobs are handled directly by the integrated soundcard of
+ // the controller. We map the rest here.
+ //
+ // * *Crossfader* slider.
+
+ c.input(0x08, 0x07).does("[Master]", "crossfader")
+
+ // #### Mic/aux and effects
+ //
+ // Sadly, the buttons *Aux*, *Deck A*, *Deck B* and *Pre-hear*
+ // of the effects and microphone sections are controlled by
+ // the hardware in a bit of a useless way, so they do nothing
+ // -- other than light up when they are pressed.
+
+ var ccIdFxBanks = function (index) {
+ banks = 5
+ params = 4
+ ids = []
+ for (var j = 0; j < banks; ++j)
+ ids.push.apply(ids, c.ccIds(index + params * j, 0xB))
+ return ids
+ }
+
+ // * Microphone *volume* control and *on/off* button.
+
+ c.input(ccIdFxBanks(0x3)).does(b.soft("[Microphone]", "pregain"))
+ c.control(c.noteIds(0x23, 0xB)).does("[Microphone]", "talkover")
+
+ // * The the *Depth* and *Mix* knobs in the *Master FX*
+ // section are mapped to *mix* and *super* of the first
+ // effect unit.
+
+ c.input(ccIdFxBanks(0x0))
+ .does("[EffectRack1_EffectUnit1]", "mix")
+ c.input(ccIdFxBanks(0x1))
+ .option(scaledDiff(1/2))
+ .does("[EffectRack1_EffectUnit1]", "super1")
+
+ // * The *beats* knob can be used to change the selected effect.
+
+ c.input(ccIdFxBanks(0x2))
+ .does("[EffectRack1_EffectUnit1]", "chain_selector")
+
+ // * The *on/off* button of the FX section completley toggles
+ // the first effect unit.
+
+ c.control(c.noteIds(0x22, 0xB))
+ .does("[EffectRack1_EffectUnit1]", "enabled")
+
+ // #### Browse
+ //
+ // * The *back* and *fwd* can be used to scroll the sidebar.
+
+ c.input(c.noteIds(0x54, 0x7)).does(
+ "[Playlist]", "SelectPrevPlaylist")
+ c.input(c.noteIds(0x56, 0x7)).does(
+ "[Playlist]", "SelectNextPlaylist")
+
+ // * The *scroll* encoder scrolls the current view. When
+ // pressed it moves faster.
+
+ scrollFaster = b.modifier()
+
+ c.input(c.noteIds(0x55, 0x7)).does(scrollFaster)
+ c.input(0x55, 0x7)
+ .when (scrollFaster,
+ b.map("[Playlist]", "SelectTrackKnob")
+ .option(scaledSelectKnob(8)))
+ .else_(b.map("[Playlist]", "SelectTrackKnob")
+ .options.selectknob)
+
+ // * The *area* toggles the maximized library.
+
+ c.control(c.noteIds(0x50, 0x7)).does(
+ "[Master]", "maximize_library")
+
+ // * The *view* button in the *browser* section lets you tap
+ // the tempo for the track that is currently on pre-hear.
+
+ this.viewButton = c.control(c.noteIds(0x51, 0x7))
+
+ // ### Per deck controls
+ //
+ // We use a `behaviou.chooser` for the PFL selection. This
+ // will make sure that only one prehear channel is selected at
+ // a time for greater convenience. Then, we define a `addDeck`
+ // function that will add the actual controls for each of the
+ // decks.
+
+ this.decks = b.chooser()
+ this.addDeck(0)
+ this.addDeck(1)
+
+ },
+
+ addDeck: function (i) {
+ var g = "[Channel" + (i+1) + "]"
+ var ccId = function (cc) { return c.ccIds(cc, 0x07+i) }
+ var ccIdShift = function (cc) { return c.ccIds(cc, 0x09+i) }
+ var ccIdAll = function (cc) { return _.union(ccId(cc),
+ ccIdShift(cc)) }
+ var noteId = function (note) { return c.noteIds(note, 0x07+i) }
+ var noteIdShift = function (note) { return c.noteIds(note, 0x09+i) }
+ var noteIdAll = function (cc) { return _.union(noteId(cc),
+ noteIdShift(cc)) }
+
+ // #### Mixer section
+ //
+ // * Pre-hear deck selection.
+
+ c.control(noteIdAll(0x0A)).does(this.decks.add(g, "pfl"))
+
+ this.viewButton.when(this.decks.activator(i),
+ g, "bpm_tap", g, "beat_active")
+
+ // * *Volume* fader and *low*, *mid*, *high* and *trim* knobs.
+ // *Trim* is the deck *gain* knob in Mixxx.
+
+ c.input(ccIdAll(0x07)).does(g, "volume")
+ c.input(ccIdAll(0x46)).does(g, "filterLow")
+ c.input(ccIdAll(0x47)).does(g, "filterMid")
+ c.input(ccIdAll(0x48)).does(g, "filterHigh")
+ c.input(ccIdAll(0x09)).does(g, "pregain")
+
+ // * *Volume* meters for each channel.
+
+ c.output(noteIdAll(0x5f)).does(b.mapOut(g, "VuMeter").meter())
+
+ // * The **fader FX** we use to control the quick filter. The
+ // **on/off** button below can be used to toggle it.
+ // Likewise, pressing the knob momentarily toggles it.
+
+ c.input(ccIdAll(0x06))
+ .option(scaledDiff(1/2))
+ .does("[QuickEffectRack1_"+g+"]", 'super1')
+ c.control(noteIdAll(0x06))
+ .does("[QuickEffectRack1_"+g+"]", 'enabled')
+ c.control(noteIdAll(0x0D))
+ .does("[QuickEffectRack1_"+g+"]", 'enabled')
+
+ // #### Effects
+ //
+ // * In the *Master FX* section, the *FX Select* left and
+ // right enable the first effect unit on the deck in the
+ // direction of the arrow.
+
+ c.control(c.noteIds(0x20+i, 0xB))
+ .does("[EffectRack1_EffectUnit1]", "group_"+g+"_enable")
+
+ // #### Browse
+ //
+ // * The *load A* or *load B* buttons load the selected track
+ // to the given deck.
+
+ c.control(c.noteIds(0x52+i, 0x7)).does(g, "LoadSelectedTrack")
+
+ // #### Deck transport
+ //
+ // * The *play* and *cue* buttons work as expected. On
+ // *shift*, the cue button does a reverse effect.
+
+ var redLed = 0x00
+ var amberLed = 0x40
+ var greenLed = 0x70
+ var pad = function (ids, color) {
+ return c.control(ids).states({
+ on: color + 0xf,
+ off: color + 0x1
+ })
+ }
+
+ pad(noteIdAll(0x17), greenLed).does(g, "play")
+ pad(noteId(0x16), redLed).does(g, "cue_default", g, "cue_indicator")
+ pad(noteIdShift(0x16), amberLed).does(g, "reverse")
+
+ // * The *keylock* button toggles the pitch-independent time
+ // stretching. On *shift*, it toggles *slip mode*, in which
+ // loops and scratching continue playback on the background
+ // thus returning the playhead to where the track would have
+ // been.
+
+ slipMode = b.switch_()
+ c.control(noteId(0x12)).does(g, "keylock")
+ c.control(noteIdShift(0x12)).does(slipMode)
+
+ // * The *sync* button. Like the button in the UI, it can be
+ // held pressed to enable the deck in the *master sync*
+ // group.
+
+ c.control(noteIdAll(0x13)).does(g, "sync_enabled")
+
+ // #### Beat grid
+ //
+ // * The *adjust* button *aligns the beatgrid* to the current
+ // play position.
+
+ c.control(noteIdAll(0x11)).does(g, "beats_translate_curpos")
+
+ // * The *set* button toggles loop and hot-cue *quantization*
+ // on or off.
+
+ c.control(noteIdAll(0x10)).does(g, "quantize")
+
+ // #### Pitch and transport bar
+ //
+ // * The *pitch* encoder moves the pitch slider up and
+ // down. When it is pressed, it moves it pitch faster.
+
+ var coarseRateFactor = 1/10
+ var coarseRateOn = b.modifier()
+
+ c.input(noteIdAll(0x03)).does(coarseRateOn)
+ c.input(ccIdAll(0x03))
+ .when (coarseRateOn,
+ b.map(g, "rate").option(scaledDiff(2)))
+ .else_(b.map(g, "rate").option(scaledDiff(1/12)))
+
+ // * In *drop* mode, the touch strip scrolls through the song.
+
+ c.input(ccId(0x34)).does(g, "playposition")
+
+ // * In *swipe* mode, the touch strip nudges the pitch up and
+ // down. When *shift* is held it simulates scratching.
+
+ c.input(ccId(0x35)).does(g, "jog")
+ .option(scaledSelectKnob(-1/3))
+ c.input(ccIdShift(0x35)).does(b.scratchTick(i+1))
+ .options.selectknob,
+ c.input(noteIdShift(0x47))
+ .does(b.scratchEnable(i+1, 128))
+ .when(slipMode, b.map(g, "slip_enabled").options.switch_)
+
+ // #### Performance modes
+ //
+ // ##### Hot cues
+ //
+ // * In *hot-cues* mode, the performance buttons control the
+ // hot cues. One may *clear* hot-cues with *shift*.
+
+ for (var j = 0; j < 8; ++j) {
+ pad(noteId(0x60+j), amberLed).does(
+ g, "hotcue_" + (j+1) + "_activate",
+ g, "hotcue_" + (j+1) + "_enabled")
+ pad(noteIdShift(0x60+j), amberLed).does(
+ g, "hotcue_" + (j+1) + "_clear",
+ g, "hotcue_" + (j+1) + "_enabled")
+ }
+
+ // ##### Slicer
+ //
+ // There is no functionality like a *slicer* in Mixxx, but we
+ // reuse these pads for various purposes in this mode.
+ //
+ // * The buttons *1 to 4* trigger the first four samplers.
+ // The sample plays as long as the button is held.
+
+ for (var j = 0; j < 4; ++j)
+ pad(noteIdAll(0x68+j), redLed).does(
+ "[Sampler" + (j+1) + "]", "cue_preview")
+
+ // * The buttons *5 and 6* trigger a *spinback* and *brake*
+ // effect respectively.
+
+ pad(noteIdAll(0x6C), greenLed).does(b.spinback(i+1))
+ pad(noteIdAll(0x6D), greenLed).does(b.brake(i+1))
+
+ // * The buttons *7 and 8* perform a stutter effect at
+ // different speeds.
+
+ pad(noteIdAll(0x6E), amberLed).does(b.stutter(g, 1/8))
+ pad(noteIdAll(0x6F), amberLed).does(b.stutter(g, 1/4))
+
+ // ##### Auto loop
+ //
+ // * In *auto-loop* mode, the pads select *loops* of sizes
+ // 0.5, 1, 2, 4, 8, 16, 32 or 64, beats (starting at the
+ // top-left pad). On *shift*, it creates loops of sizes
+ // 1/32, 1/16, 1/8, 1/4, 1/2, 1, 2, or 4 beats.
+
+ loopSize = [ "0.03125", "0.0625", "0.125", "0.25",
+ "0.5", "1", "2", "4",
+ "8", "16", "32", "64" ]
+ for (var j = 0; j < 8; ++j)
+ pad(noteId(0x70+j), greenLed).does(
+ g, "beatloop_" + loopSize[4+j] + "_toggle",
+ g, "beatloop_" + loopSize[4+j] + "_enabled")
+ for (var j = 0; j < 8; ++j)
+ pad(noteIdShift(0x70+j), greenLed).does(
+ g, "beatloop_" + loopSize[j] + "_toggle",
+ g, "beatloop_" + loopSize[j] + "_enabled")
+
+ // ##### Loop roll
+ //
+ // * In *loop-roll* mode, momentarily creates a loop and, on
+ // release returns the playhead to where it would have been
+ // without looping. Loop sizes are 1/32, 1/16, 1/8, 1/4,
+ // 1/2, 1, 2, or 4 beats (starting at the top-left pad). On
+ // *shift*, it is 0.5, 1, 2, 4, 8, 16, 32 or 64 beats.
+
+ loopSize = [ "0.03125", "0.0625", "0.125", "0.25",
+ "0.5", "1", "2", "4",
+ "8", "16", "32", "64" ]
+ for (var j = 0; j < 8; ++j)
+ pad(noteId(0x78+j), greenLed).does(
+ g, "beatlooproll_" + loopSize[j] + "_activate",
+ g, "beatloop_" + loopSize[j] + "_enabled")
+ for (var j = 0; j < 8; ++j)
+ pad(noteIdShift(0x78+j), greenLed).does(
+ g, "beatlooproll_" + loopSize[4+j] + "_activate",
+ g, "beatloop_" + loopSize[4+j] + "_enabled")
+
+ },
+
+ // ### Initialization
+ //
+ // The `preinit` function is called before the MIDI controls are
+ // initialized. We are going to set the device in *basic mode*,
+ // as mentioned in the manual. This means that mode management is
+ // done by the device -- this will simplify the script and let
+ // have direct lower latency mappings more often.
+
+ preinit: function () {
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x6f)
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x00)
+ },
+
+ init: function () {
+ this.decks.activate(0)
+ },
+
+ // ### Shutdown
+ //
+ // The documentation suggests to reset the device when the program
+ // shuts down. This means that all the lights are turned off and
+ // the device is in basic mode, ready to be used by some other
+ // program.
+
+ postshutdown: function () {
+ this.mixxx.midi.sendShortMsg(0xb7, 0x00, 0x00)
+ }
+
+});
+
+// Utilities
+// ---------
+//
+// The *scaledDiff* function returns a behaviour option that is useful
+// to define encoders with a specific sensitivity, which is useful to
+// correct the issues of the stepped encoders.
+
+function scaledDiff (factor) {
+ return function (v, v0) {
+ return (v0 + factor * (v > 64 ? v - 128 : v)).clamp(0, 128)
+ }
+}
+
+function scaledSelectKnob (factor) {
+ return function (v) {
+ return factor * (v > 64 ? v - 128 : v)
+ }
+}
+
+// > Copyright (C) 2013 Juan Pedro Bolívar Puente
+// >
+// > This program is free software: you can redistribute it and/or
+// > modify it under the terms of the GNU General Public License as
+// > published by the Free Software Foundation, either version 3 of the
+// > License, or (at your option) any later version.
+// >
+// > This program is distributed in the hope that it will be useful,
+// > but WITHOUT ANY WARRANTY; without even the implied warranty of
+// > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// > GNU General Public License for more details.
+// >
+// > You should have received a copy of the GNU General Public License
+// > along with this program. If not, see .
+
+},{"mixco":2,"underscore":16}],17:[function(require,module,exports){
+var _, assert, bind, copy, events, extend, factory, indent, isinstance, makeOptionsChooser, map, multi, option, ref, ref1, ref2, toOption, transform, value,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+transform = require('./transform');
+
+value = require('./value');
+
+ref = require('./util'), indent = ref.indent, assert = ref.assert, factory = ref.factory, copy = ref.copy;
+
+ref1 = require('heterarchy'), multi = ref1.multi, isinstance = ref1.isinstance;
+
+_ = (ref2 = require('underscore'), extend = ref2.extend, bind = ref2.bind, map = ref2.map, ref2);
+
+exports.Actor = (function(superClass) {
+ extend1(Actor, superClass);
+
+ function Actor() {
+ return Actor.__super__.constructor.apply(this, arguments);
+ }
+
+ Actor.prototype.send = void 0;
+
+ return Actor;
+
+})(events.EventEmitter);
+
+toOption = function(option) {
+ var result;
+ result = option;
+ if (isinstance(option, Function)) {
+ result = {
+ transform: option
+ };
+ }
+ if ((result.transform != null) && (result.process == null)) {
+ result.process = result.transform.length === 1 ? function(ev, b) {
+ return ev.value = this.transform(ev.value);
+ } : function(ev, b) {
+ return ev.value = this.transform(ev.value, b.midiValue);
+ };
+ }
+ return result;
+};
+
+option = exports.option = (function() {
+ var add, result, rot64;
+ result = {};
+ add = function() {
+ var desc, i, mixxxName, name, names, option;
+ names = 2 <= arguments.length ? slice.call(arguments, 0, i = arguments.length - 1) : (i = 0, []), option = arguments[i++];
+ mixxxName = names[0], name = names[1];
+ desc = toOption(option);
+ desc.name = mixxxName;
+ result[name != null ? name : mixxxName] = desc;
+ return result;
+ };
+ rot64 = function(sign) {
+ return function(v1, v0) {
+ var diff;
+ diff = v1 - (64..diff = diff === -1 || diff === 1 ? diff / 16.0 : diff - diff.sign());
+ return (v0 + diff * sign).clamp(0, 127);
+ };
+ };
+ add('invert', function(v) {
+ return 127.0 - v;
+ });
+ add('rot64', rot64(1));
+ add('rot64inv', rot64(-1));
+ add('rot64fast', function(v1, v0) {
+ return (v0 + (v1 - 64) * 1.5).clamp(0, 127);
+ });
+ add('diff', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('button', function(v) {
+ return v !== 0;
+ });
+ add('switch', function(v) {
+ return 1;
+ });
+ result.switch_ = result["switch"];
+ add('hercjog', function(v1, v0) {
+ return v0 + (v1 > 64 ? v1 - 128 : v1);
+ });
+ add('spread64', function(v) {
+ return v - 64;
+ });
+ add('selectknob', function(v) {
+ if (v > 64) {
+ return v - 128;
+ } else {
+ return v;
+ }
+ });
+ return add('soft-takeover', 'softTakeover', {
+ enable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, true);
+ }
+ },
+ disable: function(b) {
+ if (isinstance(b, exports.MapIn)) {
+ return b.script.mixxx.engine.softTakeover(b.group, b.key, false);
+ }
+ }
+ });
+})();
+
+exports.makeOptionsChooser = makeOptionsChooser = function(obj) {
+ var key, opt, result;
+ result = {};
+ for (key in option) {
+ opt = option[key];
+ Object.defineProperty(result, key, {
+ get: (function(opt) {
+ return function() {
+ return obj.option(opt);
+ };
+ })(opt)
+ });
+ }
+ return result;
+};
+
+exports.Behaviour = (function(superClass) {
+ extend1(Behaviour, superClass);
+
+ function Behaviour() {
+ return Behaviour.__super__.constructor.apply(this, arguments);
+ }
+
+ Behaviour.prototype.enable = function(script, actor) {
+ var i, len, opt, ref3, results;
+ assert(this.actor == null);
+ assert(this.script == null);
+ this.script = script;
+ this.actor = actor;
+ this._eventListener = (function(_this) {
+ return function(ev) {
+ var i, len, opt, ref3;
+ if (_this._options != null) {
+ ev = copy(ev);
+ ref3 = _this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.process === "function") {
+ opt.process(ev, _this);
+ }
+ }
+ }
+ return _this.onMidiEvent(ev);
+ };
+ })(this);
+ actor.on('event', this._eventListener);
+ if (this._options != null) {
+ ref3 = this._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ results.push(typeof opt.enable === "function" ? opt.enable(this) : void 0);
+ }
+ return results;
+ }
+ };
+
+ Behaviour.prototype.disable = function(script, actor) {
+ var i, len, opt, ref3;
+ assert(this.script === script);
+ assert(this.actor === actor);
+ if (this._options != null) {
+ ref3 = this._options;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (typeof opt.disable === "function") {
+ opt.disable(this);
+ }
+ }
+ }
+ actor.removeListener('event', this._eventListener);
+ delete this.script;
+ return delete this.actor;
+ };
+
+ Behaviour.prototype.option = function() {
+ var i, len, opt, options, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ for (i = 0, len = options.length; i < len; i++) {
+ opt = options[i];
+ assert(opt);
+ }
+ (ref3 = (this._options != null ? this._options : this._options = [])).push.apply(ref3, map(options, toOption));
+ return this;
+ };
+
+ Behaviour.property('options', function() {
+ return makeOptionsChooser(this);
+ });
+
+ Behaviour.prototype.directInMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ Behaviour.prototype.onMidiEvent = function(ev) {
+ return null;
+ };
+
+ Behaviour.prototype.getMidiValue = function() {
+ return this.value;
+ };
+
+ Behaviour.property('midiValue', function() {
+ return this.getMidiValue();
+ });
+
+ return Behaviour;
+
+})(value.Value);
+
+exports.Call = (function(superClass) {
+ extend1(Call, superClass);
+
+ function Call(onMidiEvent) {
+ this.onMidiEvent = onMidiEvent;
+ Call.__super__.constructor.call(this);
+ }
+
+ return Call;
+
+})(exports.Behaviour);
+
+exports.call = factory(exports.Call);
+
+exports.Output = (function(superClass) {
+ extend1(Output, superClass);
+
+ Output.prototype.minimum = 1;
+
+ Output.prototype.maximum = void 0;
+
+ function Output() {
+ Output.__super__.constructor.apply(this, arguments);
+ this.output = value.value();
+ }
+
+ Output.prototype.enable = function() {
+ Output.__super__.enable.apply(this, arguments);
+ if (this.actor.send != null) {
+ if (this._updateOutputCallback == null) {
+ this._updateOutputCallback = (function(_this) {
+ return function() {
+ return _this.updateOutput();
+ };
+ })(this);
+ }
+ this.output.on('value', this._updateOutputCallback);
+ }
+ if (this.actor.doSend != null) {
+ return this.updateOutput(this.actor.doSend);
+ }
+ };
+
+ Output.prototype.disable = function() {
+ if (this._updateOutputCallback != null) {
+ this.removeListener('value', this._updateOutputCallback);
+ this._updateOutputCallback = void 0;
+ }
+ return Output.__super__.disable.apply(this, arguments);
+ };
+
+ Output.prototype.updateOutput = function(sendfn) {
+ if (sendfn == null) {
+ sendfn = null;
+ }
+ if (sendfn == null) {
+ sendfn = this.actor.send;
+ }
+ return sendfn.call(this.actor, (Math.abs(this.output.value) >= this.minimum ? 'on' : 'off'));
+ };
+
+ return Output;
+
+})(exports.Behaviour);
+
+exports.Transform = (function(superClass) {
+ extend1(Transform, superClass);
+
+ function Transform(transformer1, initial) {
+ this.transformer = transformer1;
+ if (initial == null) {
+ initial = void 0;
+ }
+ Transform.__super__.constructor.call(this, {
+ initial: initial
+ });
+ }
+
+ Transform.prototype.onMidiEvent = function(ev) {
+ var result;
+ result = this.transformer(ev, this.midiValue);
+ if (result != null) {
+ return this.output.value = this.value = result;
+ }
+ };
+
+ Transform.prototype.getMidiValue = function() {
+ var base, ref3;
+ return (ref3 = typeof (base = this.transformer).inverse === "function" ? base.inverse(this.value) : void 0) != null ? ref3 : this.value;
+ };
+
+ return Transform;
+
+})(exports.Output);
+
+exports.transform = factory(exports.Transform);
+
+exports.modifier = function() {
+ return exports.transform(transform.momentaryT, false);
+};
+
+exports["switch"] = function() {
+ return exports.transform(transform.binaryT, false);
+};
+
+exports.switch_ = exports["switch"];
+
+exports.MapIn = (function(superClass) {
+ extend1(MapIn, superClass);
+
+ function MapIn(ingroupOrParams, inkey) {
+ var ref3;
+ if (inkey == null) {
+ inkey = void 0;
+ }
+ MapIn.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(ingroupOrParams, String) ? ingroupOrParams : {
+ group: ingroupOrParams,
+ key: inkey
+ }, this.group = ref3.group, this.key = ref3.key;
+ this._transform = transform.mappings[this.key];
+ }
+
+ MapIn.prototype.transform = function(trans) {
+ this._transform = trans;
+ return this;
+ };
+
+ MapIn.prototype.enable = function(script, actor) {
+ var engine;
+ MapIn.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.value = engine.getValue(this.group, this.key);
+ if (this.listeners('value').length > 0) {
+ if (this._inHandler == null) {
+ this._inHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.group, this.key, this._inHandler);
+ return this._inHandlerConnected = true;
+ }
+ };
+
+ MapIn.prototype.disable = function() {
+ if (this._inHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.group, this.key, this._inHandler, true);
+ this._inHandlerConnected = false;
+ }
+ return MapIn.__super__.disable.apply(this, arguments);
+ };
+
+ MapIn.prototype.directInMapping = function() {
+ if (this._transform === transform.mappings[this.key]) {
+ return {
+ group: this.group,
+ key: this.key
+ };
+ }
+ };
+
+ MapIn.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this._transform(ev, this.midiValue);
+ if (val != null) {
+ this.script.mixxx.engine.setValue(this.group, this.key, val);
+ if (this.listeners('value').length === 0) {
+ return this.value = val;
+ }
+ }
+ };
+
+ MapIn.prototype.getMidiValue = function() {
+ var ref3, ref4;
+ return (ref3 = (ref4 = this._transform) != null ? typeof ref4.inverse === "function" ? ref4.inverse(this.value) : void 0 : void 0) != null ? ref3 : this.value;
+ };
+
+ return MapIn;
+
+})(exports.Behaviour);
+
+exports.mapIn = factory(exports.MapIn);
+
+exports.MapOut = (function(superClass) {
+ extend1(MapOut, superClass);
+
+ function MapOut(outgroupOrParams, outkey) {
+ var ref3;
+ if (outkey == null) {
+ outkey = void 0;
+ }
+ MapOut.__super__.constructor.apply(this, arguments);
+ ref3 = !isinstance(outgroupOrParams, String) ? outgroupOrParams : {
+ outgroup: outgroupOrParams,
+ outkey: outkey
+ }, this.outgroup = ref3.outgroup, this.outkey = ref3.outkey;
+ }
+
+ MapOut.prototype.meter = function(transformer) {
+ if (transformer == null) {
+ transformer = void 0;
+ }
+ this._outTransform = transformer;
+ if (this._outTransform == null) {
+ this._outTransform = transform.mappings[this.outkey].inverse;
+ }
+ this.updateOutput = function() {
+ return this.actor.send(Math.floor(this._outTransform(this.output.value)));
+ };
+ return this;
+ };
+
+ MapOut.prototype.enable = function(script, actor) {
+ var engine;
+ MapOut.__super__.enable.apply(this, arguments);
+ engine = script.mixxx.engine;
+ this.output.value = engine.getValue(this.outgroup, this.outkey);
+ if (this.output.listeners('value').length > 0) {
+ if (this._outHandler == null) {
+ this._outHandler = script.registerHandler((function(_this) {
+ return function(v) {
+ return _this.output.value = v;
+ };
+ })(this));
+ }
+ engine.connectControl(this.outgroup, this.outkey, this._outHandler);
+ return this._outHandlerConnected = true;
+ }
+ };
+
+ MapOut.prototype.disable = function() {
+ if (this._outHandlerConnected != null) {
+ this.script.mixxx.engine.connectControl(this.outgroup, this.outkey, this._outHandler, true);
+ this._outHandlerConnected = false;
+ }
+ return MapOut.__super__.disable.apply(this, arguments);
+ };
+
+ MapOut.prototype.directOutMapping = function() {
+ if (this._outTransform == null) {
+ return {
+ group: this.outgroup,
+ key: this.outkey,
+ minimum: this.minimum
+ };
+ }
+ };
+
+ return MapOut;
+
+})(exports.Output);
+
+exports.mapOut = factory(exports.MapOut);
+
+exports.Map = (function(superClass) {
+ extend1(Map, superClass);
+
+ function Map(groupOrParams, key, outgroup, outkey) {
+ var params;
+ params = !isinstance(groupOrParams, String) ? groupOrParams : {
+ group: groupOrParams,
+ key: key,
+ outgroup: outgroup,
+ outkey: outkey
+ };
+ if (params.outgroup == null) {
+ params.outgroup = params.group;
+ }
+ if (params.outkey == null) {
+ params.outkey = params.key;
+ }
+ Map.__super__.constructor.call(this, params);
+ }
+
+ return Map;
+
+})(multi(exports.MapIn, exports.MapOut));
+
+exports.map = factory(exports.Map);
+
+exports.toBehaviour = function() {
+ var args, behaviour;
+ behaviour = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ if (args.length > 0) {
+ return exports.map.apply(exports, [behaviour].concat(slice.call(args)));
+ } else {
+ return behaviour;
+ }
+};
+
+exports.soft = function() {
+ return exports.map.apply(exports, arguments).option(option.softTakeover);
+};
+
+exports.toggle = function() {
+ var args, offValue, onValue;
+ offValue = arguments[0], onValue = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+ return exports.map.apply(exports, args).transform(function(ev) {
+ if (ev.pressed) {
+ return onValue;
+ } else {
+ return offValue;
+ }
+ });
+};
+
+exports.set = function() {
+ var args, valueToSet;
+ valueToSet = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.toggle.apply(exports, [valueToSet, null].concat(slice.call(args)));
+};
+
+exports.Chooser = (function(superClass) {
+ extend1(Chooser, superClass);
+
+ function Chooser(arg) {
+ var ref3;
+ ref3 = arg != null ? arg : {}, this.autoExclusive = ref3.autoExclusive, this.onDisable = ref3.onDisable;
+ Chooser.__super__.constructor.apply(this, arguments);
+ this._selectedIndex = null;
+ this._chooseOptions = [];
+ this._chooseActivators = [];
+ this._chooseSelectors = [];
+ this._chooseHandles = [];
+ }
+
+ Chooser.prototype.add = function(group, key, listen) {
+ var activator, idx;
+ if (listen == null) {
+ listen = null;
+ }
+ idx = this._chooseOptions.length;
+ activator = exports.map(group, key).transform((function(_this) {
+ return function(ev) {
+ if (ev.pressed) {
+ _this.activate(idx);
+ }
+ return null;
+ };
+ })(this));
+ this._chooseOptions.push([group, key, listen]);
+ this._chooseActivators.push(activator);
+ return activator;
+ };
+
+ Chooser.prototype.enable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ Chooser.__super__.enable.apply(this, arguments);
+ if (this._updateValueHandler == null) {
+ this._updateValueHandler = script.registerHandler((function(_this) {
+ return function() {
+ return _this._updateValue();
+ };
+ })(this));
+ }
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler);
+ }
+ return this._updateValue();
+ };
+
+ Chooser.prototype.disable = function(script) {
+ var engine, group, i, key, len, listen, ref3, ref4;
+ assert(this._updateValueHandler);
+ engine = script.mixxx.engine;
+ ref3 = this._chooseOptions;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ ref4 = ref3[i], group = ref4[0], key = ref4[1], listen = ref4[2];
+ if (listen == null) {
+ listen = key;
+ }
+ engine.connectControl(group, listen, this._updateValueHandler, true);
+ }
+ return Chooser.__super__.disable.apply(this, arguments);
+ };
+
+ Chooser.prototype.activator = function(idx) {
+ assert((0 <= idx && idx < this._chooseOptions.length));
+ return this._chooseActivators[idx];
+ };
+
+ Chooser.prototype.selector = function() {
+ var select, selector;
+ select = (function(_this) {
+ return function(ev) {
+ var v;
+ v = (ev.value / 128.0 * _this._chooseOptions.length).clamp(0, _this._chooseOptions.length - 1);
+ _this._update({
+ index: Math.floor(v)
+ });
+ return v;
+ };
+ })(this);
+ select.inverse = (function(_this) {
+ return function(v) {
+ return v / _this._chooseOptions.length * 128.0;
+ };
+ })(this);
+ selector = extend(exports.transform(select), {
+ _updateValue: function(newv) {
+ if (Math.floor(newv) !== Math.floor(this.value)) {
+ return this.value = this.output.value = newv;
+ }
+ }
+ });
+ this._chooseSelectors.push(selector);
+ return selector;
+ };
+
+ Chooser.prototype.momentary = function() {
+ return exports.action({
+ press: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: true
+ });
+ };
+ })(this),
+ release: (function(_this) {
+ return function() {
+ return _this._update({
+ enable: false
+ });
+ };
+ })(this)
+ });
+ };
+
+ Chooser.prototype.activate = function(idx) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ return this;
+ };
+
+ Chooser.prototype.select = function(idx) {
+ if (this.actor != null) {
+ this._update({
+ index: idx,
+ enable: true
+ });
+ } else {
+ this._selectedIndex = idx;
+ }
+ return this;
+ };
+
+ Chooser.prototype.onMidiEvent = function(event) {
+ var enable;
+ if (event.pressed) {
+ enable = !this.value;
+ this._update({
+ enable: enable
+ });
+ if (!enable) {
+ return typeof this.onDisable === "function" ? this.onDisable() : void 0;
+ }
+ }
+ };
+
+ Chooser.prototype._update = function(arg) {
+ var enable, group, i, idx, index, key, len, listen, ref3, ref4, ref5, ref6, ref7, script;
+ ref3 = arg != null ? arg : {}, index = ref3.index, enable = ref3.enable;
+ if (enable == null) {
+ enable = this.value;
+ }
+ if (index == null) {
+ index = this._selectedIndex;
+ }
+ index = index != null ? index.clamp(0, this._chooseOptions.length - 1) : void 0;
+ if (index !== this._selectedIndex || enable !== this.value) {
+ script = (ref4 = this.script) != null ? ref4 : this._chooseActivators[index].script;
+ if (index != null) {
+ ref5 = this._chooseOptions[index], group = ref5[0], key = ref5[1], listen = ref5[2];
+ script.mixxx.engine.setValue(group, key, enable);
+ }
+ if (!this.autoExclusive || !enable) {
+ ref6 = this._chooseOptions;
+ for (idx = i = 0, len = ref6.length; i < len; idx = ++i) {
+ ref7 = ref6[idx], group = ref7[0], key = ref7[1];
+ if (idx !== index) {
+ script.mixxx.engine.setValue(group, key, false);
+ }
+ }
+ }
+ return this._selectedIndex = index;
+ }
+ };
+
+ Chooser.prototype._updateValue = function() {
+ var engine, i, len, ref3, selector;
+ if (this.script != null) {
+ engine = this.script.mixxx.engine;
+ this.value = this.output.value = _.some(this._chooseOptions, function(arg) {
+ var group, key, listen;
+ group = arg[0], key = arg[1], listen = arg[2];
+ if (listen == null) {
+ listen = key;
+ }
+ return engine.getValue(group, listen);
+ });
+ ref3 = this._chooseSelectors;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ selector = ref3[i];
+ selector._updateValue(this._selectedIndex);
+ }
+ }
+ return this;
+ };
+
+ return Chooser;
+
+})(exports.Output);
+
+exports.chooser = factory(exports.Chooser);
+
+exports.When = (function(superClass) {
+ extend1(When, superClass);
+
+ function When() {
+ var _condition, base, wrapped;
+ _condition = arguments[0], wrapped = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this._condition = _condition;
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.when = this["else"].when;
+ this.else_ = this["else"];
+ When.__super__.constructor.call(this);
+ this._wrapped = exports.toBehaviour.apply(exports, wrapped);
+ this._condition.on('value', (function(_this) {
+ return function() {
+ return _this._update();
+ };
+ })(this));
+ if (this._lastCondition !== 'no-more-negations') {
+ this._lastCondition = this._condition;
+ if ((base = this._lastCondition).negation == null) {
+ base.negation = value.not(this._condition);
+ }
+ }
+ }
+
+ When.prototype.option = function() {
+ var ref3;
+ When.__super__.option.apply(this, arguments);
+ (ref3 = this._wrapped).option.apply(ref3, arguments);
+ return this;
+ };
+
+ When.prototype._elseWhen = function() {
+ var args, condition, nextCondition;
+ condition = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = value.and(condition, value.not(this._lastCondition));
+ nextCondition.negation = value.and(this._lastCondition.negation, value.not(condition));
+ this._lastCondition = nextCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype._else = function() {
+ var args, nextCondition;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastCondition != null, "Can not define more conditions after 'else'");
+ nextCondition = this._lastCondition.negation;
+ nextCondition.negation = 'no-more-negations';
+ delete this._lastCondition;
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(exports.When, [nextCondition].concat(slice.call(args)), function(){});
+ };
+
+ When.prototype.enable = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ When.__super__.enable.apply(this, arguments);
+ this._enableOn = args;
+ this._enableRequested = true;
+ return this._update();
+ };
+
+ When.prototype.disable = function() {
+ this._enableRequested = false;
+ this._update();
+ return When.__super__.disable.apply(this, arguments);
+ };
+
+ When.prototype._update = function() {
+ var ref3, ref4;
+ this.value = this._enableRequested && this._condition.value;
+ if (this._wrapped.actor && !this.value) {
+ (ref3 = this._wrapped).disable.apply(ref3, this._enableOn);
+ }
+ if (!this._wrapped.actor && this.value) {
+ return (ref4 = this._wrapped).enable.apply(ref4, this._enableOn);
+ }
+ };
+
+ When.prototype.directOutMapping = function() {
+ return null;
+ };
+
+ When.prototype.directInMapping = function() {
+ return null;
+ };
+
+ return When;
+
+})(exports.Behaviour);
+
+exports.when = factory(exports.When);
+
+exports.Action = (function(superClass) {
+ extend1(Action, superClass);
+
+ Action.prototype.minimum = true;
+
+ function Action(action) {
+ this.action = action != null ? action : void 0;
+ Action.__super__.constructor.call(this);
+ if (this.onPress == null) {
+ this.onPress = this.action.press;
+ }
+ if (this.onRelease == null) {
+ this.onRelease = this.action.release;
+ }
+ }
+
+ Action.prototype.onMidiEvent = function(ev) {
+ var val;
+ val = this.value = this.output.value = ev.pressed;
+ if (val) {
+ return typeof this.onPress === "function" ? this.onPress() : void 0;
+ } else {
+ return typeof this.onRelease === "function" ? this.onRelease() : void 0;
+ }
+ };
+
+ return Action;
+
+})(exports.Output);
+
+exports.action = factory(exports.Action);
+
+exports.punchIn = function(threshold, threshold2) {
+ var inThreshold, oldxfader;
+ if (threshold2 == null) {
+ threshold2 = void 0;
+ }
+ oldxfader = void 0;
+ inThreshold = function(newxfader, threshold) {
+ return (threshold < 0 && newxfader < threshold) || (threshold > 0 && newxfader > threshold);
+ };
+ return exports.action({
+ press: function() {
+ var engine, newxfader;
+ engine = this.script.mixxx.engine;
+ newxfader = engine.getValue("[Master]", "crossfader");
+ if (inThreshold(newxfader, threshold) || ((threshold2 != null) && inThreshold(newxfader, threshold2))) {
+ oldxfader = newxfader;
+ return engine.setValue("[Master]", "crossfader", 0);
+ }
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (oldxfader != null) {
+ engine.setValue("[Master]", "crossfader", oldxfader);
+ return oldxfader = void 0;
+ }
+ }
+ });
+};
+
+exports.scratchEnable = function(deck, intervalsPerRev, rpm, alpha, beta, ramp) {
+ if (intervalsPerRev == null) {
+ intervalsPerRev = 128 * 4;
+ }
+ if (rpm == null) {
+ rpm = 44.0;
+ }
+ if (alpha == null) {
+ alpha = 1.0 / 8.0;
+ }
+ if (beta == null) {
+ beta = 1.0 / 8.0 / 32.0;
+ }
+ if (ramp == null) {
+ ramp = true;
+ }
+ return exports.action({
+ press: function() {
+ var enable;
+ enable = this.script.mixxx.engine.scratchEnable;
+ return enable(deck, intervalsPerRev, rpm, alpha, beta, ramp);
+ },
+ release: function() {
+ return this.script.mixxx.engine.scratchDisable(deck, ramp);
+ }
+ });
+};
+
+exports.scratchTick = function(deck, transform) {
+ if (transform == null) {
+ transform = function(x) {
+ return x;
+ };
+ }
+ return exports.call(function(ev) {
+ var engine;
+ engine = this.script.mixxx.engine;
+ return engine.scratchTick(deck, transform(ev.value));
+ });
+};
+
+exports.spinback = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).spinback.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.brake = function() {
+ var args, deck;
+ deck = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ return exports.modifier().on('value', function() {
+ var ref3;
+ return (ref3 = this.script.mixxx.engine).brake.apply(ref3, [deck, this.value].concat(slice.call(args)));
+ });
+};
+
+exports.playhead = function(g) {
+ return exports.mapOut(g, "playposition").meter((function() {
+ var step;
+ step = 0;
+ return function(pos) {
+ var duration, engine;
+ engine = this.script.mixxx.engine;
+ duration = (function() {
+ switch (false) {
+ case !!engine.getValue(g, "play"):
+ return void 0;
+ case !(pos > .9):
+ return 5;
+ case !(pos > .8):
+ return 9;
+ case !(pos > .75):
+ return 13;
+ default:
+ return void 0;
+ }
+ })();
+ if (duration != null) {
+ step = (step + 1) % duration;
+ if (step > duration / 2) {
+ return 0;
+ } else {
+ return pos * 127;
+ }
+ } else {
+ step = 0;
+ return pos * 127;
+ }
+ };
+ })());
+};
+
+exports.beatEffect = function(channel, type) {
+ var i, len, result, size, sizes;
+ if (type == null) {
+ type = '';
+ }
+ sizes = ["0.0625", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64"];
+ result = exports.chooser({
+ autoExclusive: true,
+ onDisable: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ if (type !== 'roll' && engine.getValue(channel, "loop_enabled")) {
+ return engine.setValue(channel, "reloop_exit", true);
+ }
+ }
+ });
+ for (i = 0, len = sizes.length; i < len; i++) {
+ size = sizes[i];
+ result.add(channel, "beatloop" + type + "_" + size + "_activate", "beatloop_" + size + "_enabled");
+ }
+ return result.select(4);
+};
+
+exports.stutter = function(group, beats) {
+ var tick;
+ if (beats == null) {
+ beats = 0.25;
+ }
+ tick = function() {
+ var engine, gain, newgain;
+ engine = this.script.mixxx.engine;
+ gain = engine.getValue(group, "pregain");
+ newgain = gain > 0 ? (this._oldgain = gain, 0) : this._oldgain;
+ return engine.setValue(group, "pregain", newgain);
+ };
+ return exports.action({
+ press: function() {
+ var bpm, delta, engine;
+ engine = this.script.mixxx.engine;
+ bpm = engine.getValue(group, "bpm");
+ delta = beats * 60000 / bpm;
+ if (this._timerHandle == null) {
+ this._timerHandle = this.script.registerHandler(bind(tick, this));
+ }
+ return this._timerId != null ? this._timerId : this._timerId = engine.beginTimer(delta, this._timerHandle);
+ },
+ release: function() {
+ var engine;
+ engine = this.script.mixxx.engine;
+ engine.stopTimer(this._timerId);
+ if (this._oldgain != null) {
+ engine.setValue(group, "pregain", this._oldgain);
+ }
+ delete this._timerId;
+ return delete this._oldgain;
+ }
+ });
+};
+
+
+},{"./transform":21,"./util":22,"./value":23,"events":10,"heterarchy":13,"underscore":16}],18:[function(require,module,exports){
+var assert, exports, konsole;
+
+assert = require('./util').assert;
+
+konsole = this;
+
+exports = konsole;
+
+if (konsole.log == null) {
+ konsole.log = function() {
+ return print("" + arguments);
+ };
+}
+
+if (konsole.info == null) {
+ konsole.info = konsole.log;
+}
+
+if (konsole.warn == null) {
+ konsole.warn = konsole.log;
+}
+
+if (konsole.error == null) {
+ konsole.error = konsole.log;
+}
+
+if (konsole.time == null) {
+ konsole.time = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.timeEnd == null) {
+ konsole.timeEnd = function() {
+ return assert(False, "time not implemented in konsole");
+ };
+}
+
+if (konsole.trace == null) {
+ konsole.trace = function() {
+ var err;
+ err = new Error();
+ err.name = "Trace";
+ err.message = "" + arguments;
+ return konsole.error(err.stack);
+ };
+}
+
+if (konsole.dir == null) {
+ konsole.dir = function() {
+ return konsole.log(object + "\n");
+ };
+}
+
+if (konsole.assert == null) {
+ konsole.assert = assert;
+}
+
+
+},{"./util":22}],19:[function(require,module,exports){
+var MIDI_CC, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCHBEND, assert, behaviour, ccIds, event, extend, factory, hexStr, indent, joinLn, midiId, multi, noteIds, noteOnIds, pbIds, ref, ref1, some, xmlTag,
+ slice = [].slice,
+ extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty;
+
+multi = require('heterarchy').multi;
+
+ref = require('./util'), indent = ref.indent, hexStr = ref.hexStr, assert = ref.assert, factory = ref.factory, xmlTag = ref.xmlTag, joinLn = ref.joinLn;
+
+behaviour = require('./behaviour');
+
+ref1 = require('underscore'), some = ref1.some, extend = ref1.extend;
+
+exports.MIDI_NOTE_ON = MIDI_NOTE_ON = 0x9;
+
+exports.MIDI_NOTE_OFF = MIDI_NOTE_OFF = 0x8;
+
+exports.MIDI_CC = MIDI_CC = 0xB;
+
+exports.MIDI_PITCHBEND = MIDI_PITCHBEND = 0xE;
+
+midiId = function(message, midino, channel) {
+ if (message == null) {
+ message = MIDI_CC;
+ }
+ if (midino == null) {
+ midino = 0;
+ }
+ if (channel == null) {
+ channel = 0;
+ }
+ return {
+ message: message,
+ midino: midino,
+ channel: channel,
+ status: function() {
+ return (this.message << 4) | this.channel;
+ },
+ configMidi: function(depth) {
+ return (indent(depth)) + "" + (hexStr(this.status())) + "\n" + (indent(depth)) + "" + (hexStr(this.midino)) + "";
+ }
+ };
+};
+
+exports.midiId = midiId;
+
+pbIds = function() {
+ return [midiId.apply(null, [MIDI_PITCHBEND, 0].concat(slice.call(arguments)))];
+};
+
+noteOnIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments)))];
+};
+
+noteIds = function() {
+ return [midiId.apply(null, [MIDI_NOTE_ON].concat(slice.call(arguments))), midiId.apply(null, [MIDI_NOTE_OFF].concat(slice.call(arguments)))];
+};
+
+ccIds = function() {
+ return [midiId.apply(null, [MIDI_CC].concat(slice.call(arguments)))];
+};
+
+exports.pbIds = pbIds;
+
+exports.noteOnIds = noteOnIds;
+
+exports.noteIds = noteIds;
+
+exports.ccIds = ccIds;
+
+exports.event = event = function(channel, control, value, status, group) {
+ return {
+ channel: channel,
+ control: control,
+ value: (function() {
+ switch (status >> 4) {
+ case MIDI_PITCHBEND:
+ return (value * 128.0 + control) / 128.0;
+ default:
+ return value;
+ }
+ })(),
+ status: status,
+ group: group,
+ message: function() {
+ return this.status >> 4;
+ },
+ pressed: status >> 4 !== MIDI_NOTE_OFF && value
+ };
+};
+
+exports.Control = (function(superClass) {
+ extend1(Control, superClass);
+
+ function Control() {
+ var args, ids;
+ ids = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.ids = ids != null ? ids : [midiId()];
+ this["else"] = (function(_this) {
+ return function() {
+ return _this._else.apply(_this, arguments);
+ };
+ })(this);
+ this["else"].when = (function(_this) {
+ return function() {
+ return _this._elseWhen.apply(_this, arguments);
+ };
+ })(this);
+ this.else_ = this["else"];
+ Control.__super__.constructor.call(this);
+ if (!(this.ids instanceof Array)) {
+ this.ids = ccIds.apply(null, [this.ids].concat(slice.call(args)));
+ }
+ this._behaviours = [];
+ if (typeof this._controlRegistry === "function") {
+ this._controlRegistry(this);
+ }
+ }
+
+ Control.prototype.does = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._behaviours.push(this.registerBehaviour(behaviour.toBehaviour.apply(behaviour, args)));
+ return this;
+ };
+
+ Control.prototype.when = function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit);
+ this._lastWhen = behaviour.when.apply(behaviour, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._elseWhen = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'elseWhen' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen["else"]).when.apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ return this;
+ };
+
+ Control.prototype._else = function() {
+ var args, ref2;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(this._lastWhen != null, "'else' must be preceded by 'when' or 'elseWhen'");
+ this._lastWhen = (ref2 = this._lastWhen)["else"].apply(ref2, args);
+ this._behaviours.push(this.registerBehaviour(this._lastWhen));
+ this._lastWhen = void 0;
+ return this;
+ };
+
+ Control.prototype.init = function(script) {
+ var b, i, len, ref2;
+ this.script = script;
+ assert(!this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.enable(script, this);
+ }
+ return this._isInit = true;
+ };
+
+ Control.prototype.shutdown = function(script) {
+ var b, i, len, ref2;
+ assert(script === this.script);
+ assert(this._isInit);
+ ref2 = this._behaviours;
+ for (i = 0, len = ref2.length; i < len; i++) {
+ b = ref2[i];
+ b.disable(script, this);
+ }
+ this._isInit = false;
+ return delete this.script;
+ };
+
+ Control.prototype.registerBehaviour = function(b) {
+ return b;
+ };
+
+ Control.prototype.configInputs = function(depth, script) {};
+
+ Control.prototype.configOutputs = function(depth, script) {};
+
+ Control.prototype.setRegistry = function(registry) {
+ assert((this._controlRegistry == null) || (registry == null));
+ return this._controlRegistry = registry;
+ };
+
+ return Control;
+
+})(behaviour.Actor);
+
+exports.InControl = (function(superClass) {
+ extend1(InControl, superClass);
+
+ function InControl() {
+ return InControl.__super__.constructor.apply(this, arguments);
+ }
+
+ InControl.prototype.init = function(script) {
+ InControl.__super__.init.apply(this, arguments);
+ if (this.needsHandler()) {
+ return script.registerHandler(((function(_this) {
+ return function() {
+ var args;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ return _this.emit('event', event.apply(null, args));
+ };
+ })(this)), this.handlerId());
+ }
+ };
+
+ InControl.prototype.option = function() {
+ var beh, i, len, options, ref2, ref3;
+ options = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ (ref2 = (this._options != null ? this._options : this._options = [])).push.apply(ref2, options);
+ ref3 = this._behaviours;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ beh = ref3[i];
+ beh.option.apply(beh, options);
+ }
+ return this;
+ };
+
+ InControl.property('options', function() {
+ return behaviour.makeOptionsChooser(this);
+ });
+
+ InControl.prototype.registerBehaviour = function(beh) {
+ if (this._options != null) {
+ beh.option.apply(beh, this._options);
+ }
+ return beh;
+ };
+
+ InControl.prototype.needsHandler = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directInMapping() || some(this._behaviours[0]._options, function(opt) {
+ return !opt.name;
+ });
+ };
+
+ InControl.prototype.handlerId = function() {
+ return "x" + (this.ids[0].status().toString(16)) + "_x" + (this.ids[0].midino.toString(16));
+ };
+
+ InControl.prototype.configInputs = function(depth, script) {
+ var id, mapping;
+ if (this.needsHandler()) {
+ mapping = {
+ group: "[Master]",
+ key: script.handlerKey(this.handlerId())
+ };
+ } else {
+ mapping = this._behaviours[0].directInMapping();
+ }
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configInMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ };
+
+ InControl.prototype.configInMapping = function(depth, mapping, id) {
+ return (indent(depth)) + "\n" + (indent(depth + 1)) + "" + mapping.group + "\n" + (indent(depth + 1)) + "" + mapping.key + "\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "\n" + (indent(depth)) + "";
+ };
+
+ InControl.prototype.configOptions = function(depth) {
+ var opt, ref2;
+ if (this.needsHandler()) {
+ return (indent(depth)) + "";
+ } else if (((ref2 = this._behaviours[0]._options) != null ? ref2.length : void 0) > 0) {
+ return joinLn((function() {
+ var i, len, ref3, results;
+ ref3 = this._behaviours[0]._options;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ opt = ref3[i];
+ if (opt.name != null) {
+ results.push((indent(depth)) + "<" + opt.name + "/>");
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ }).call(this));
+ } else {
+ return (indent(depth)) + "";
+ }
+ };
+
+ return InControl;
+
+})(exports.Control);
+
+exports.OutControl = (function(superClass) {
+ extend1(OutControl, superClass);
+
+ function OutControl() {
+ OutControl.__super__.constructor.apply(this, arguments);
+ this._states = {
+ on: 0x7f,
+ off: 0x00,
+ disable: 0x00
+ };
+ }
+
+ OutControl.prototype.send = function(state) {
+ return this.doSend(state);
+ };
+
+ OutControl.prototype.states = function(states) {
+ extend(this._states, states);
+ return this;
+ };
+
+ OutControl.prototype.doSend = function(state) {
+ var i, id, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ if (id.message !== MIDI_NOTE_OFF) {
+ if (state in this._states) {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, this._states[state]));
+ } else {
+ results.push(this.script.mixxx.midi.sendShortMsg(id.status(), id.midino, state));
+ }
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ OutControl.prototype.init = function() {
+ if (!this.needsSend()) {
+ this.send = void 0;
+ }
+ return OutControl.__super__.init.apply(this, arguments);
+ };
+
+ OutControl.prototype.shutdown = function() {
+ this.doSend('disable');
+ return OutControl.__super__.shutdown.apply(this, arguments);
+ };
+
+ OutControl.prototype.needsSend = function() {
+ return this._behaviours.length !== 1 || !this._behaviours[0].directOutMapping();
+ };
+
+ OutControl.prototype.configOutputs = function(depth, script) {
+ var id, mapping;
+ mapping = !this.needsSend() && this._behaviours[0].directOutMapping();
+ if (mapping) {
+ return joinLn((function() {
+ var i, len, ref2, results;
+ ref2 = this.ids;
+ results = [];
+ for (i = 0, len = ref2.length; i < len; i++) {
+ id = ref2[i];
+ results.push(this.configOutMapping(depth, mapping, id));
+ }
+ return results;
+ }).call(this));
+ }
+ };
+
+ OutControl.prototype.configOutMapping = function(depth, mapping, id) {
+ var options;
+ if (id.message !== MIDI_NOTE_OFF) {
+ options = joinLn([xmlTag('minimum', mapping.minimum, depth + 1), xmlTag('maximum', mapping.maximum, depth + 1)]);
+ return (indent(depth)) + "";
+ }
+ };
+
+ return OutControl;
+
+})(exports.Control);
+
+exports.input = factory(exports.InControl);
+
+exports.output = factory(exports.OutControl);
+
+exports.InOutControl = (function(superClass) {
+ extend1(InOutControl, superClass);
+
+ function InOutControl() {
+ return InOutControl.__super__.constructor.apply(this, arguments);
+ }
+
+ return InOutControl;
+
+})(multi(exports.InControl, exports.OutControl));
+
+exports.control = factory(exports.InOutControl);
+
+
+},{"./behaviour":17,"./util":22,"heterarchy":13,"underscore":16}],20:[function(require,module,exports){
+(function (process){
+var Control, S, _, assert, basename, bind, catching, flatten, indent, issubclass, mro, ref, ref1, ref2, xmlEscape,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ slice = [].slice;
+
+ref = require('underscore'), flatten = ref.flatten, bind = ref.bind;
+
+ref1 = require('heterarchy'), issubclass = ref1.issubclass, mro = ref1.mro;
+
+Control = require('./control').Control;
+
+ref2 = require('./util'), indent = ref2.indent, xmlEscape = ref2.xmlEscape, catching = ref2.catching, assert = ref2.assert;
+
+require('./console');
+
+basename = require('path').basename;
+
+S = require('string');
+
+_ = require('underscore');
+
+exports.nameFromFilename = function(fname) {
+ var extensions, name;
+ extensions = [".mixco.coffee", ".mixco.litcoffee", ".mixco.js", ".mixco"];
+ fname = basename(fname);
+ assert(_.some(extensions, function(x) {
+ return S(fname).endsWith(x);
+ }), "Script file name: " + fname + " must end in one of: " + extensions);
+ name = extensions.reduce((function(fname, ext) {
+ return fname.replace(ext, "");
+ }), fname);
+ assert(name.match(/^[a-zA-Z_$][0-9a-zA-Z_$].*$/, "Script name must be a valid JavaScript identifier"));
+ return name;
+};
+
+exports.register = function(targetModule, scriptTypeOrDefinition) {
+ var instance, name, scriptType;
+ name = targetModule.filename != null ? exports.nameFromFilename(targetModule.filename) : typeof MIXCO_SCRIPT_FILENAME !== "undefined" && MIXCO_SCRIPT_FILENAME !== null ? exports.nameFromFilename(MIXCO_SCRIPT_FILENAME) : assert(false, "Invalid script");
+ scriptType = issubclass(scriptTypeOrDefinition, exports.Script) ? scriptTypeOrDefinition : exports.create(scriptTypeOrDefinition);
+ instance = new scriptType;
+ instance.__registeredName = name;
+ targetModule.exports[name] = instance;
+ if (targetModule === require.main) {
+ return instance.main();
+ }
+};
+
+exports.create = function(scriptDefinition) {
+ var NewScript, constructor, init, k, shutdown, special, v;
+ assert(scriptDefinition.constructor != null, "Script definition must have a constructor");
+ constructor = scriptDefinition.constructor, init = scriptDefinition.init, shutdown = scriptDefinition.shutdown;
+ NewScript = (function(superClass) {
+ extend(NewScript, superClass);
+
+ function NewScript() {
+ NewScript.__super__.constructor.apply(this, arguments);
+ try {
+ Control.prototype.setRegistry(bind(this.add, this));
+ constructor.apply(this, arguments);
+ } finally {
+ Control.prototype.setRegistry(null);
+ }
+ this;
+ }
+
+ NewScript.prototype.init = function() {
+ var ref3;
+ if ((ref3 = this.preinit) != null) {
+ ref3.apply(this, arguments);
+ }
+ NewScript.__super__.init.apply(this, arguments);
+ return init != null ? init.apply(this, arguments) : void 0;
+ };
+
+ NewScript.prototype.shutdown = function() {
+ var ref3;
+ if (shutdown != null) {
+ shutdown.apply(this, arguments);
+ }
+ NewScript.__super__.shutdown.apply(this, arguments);
+ return (ref3 = this.postshutdown) != null ? ref3.apply(this, arguments) : void 0;
+ };
+
+ return NewScript;
+
+ })(exports.Script);
+ special = ['name', 'constructor', 'init', 'shutdown'];
+ for (k in scriptDefinition) {
+ v = scriptDefinition[k];
+ if (indexOf.call(special, k) < 0) {
+ NewScript.prototype[k] = v;
+ }
+ }
+ return NewScript;
+};
+
+exports.Script = (function() {
+ Script.prototype.info = {
+ name: "[mixco] Generic Script",
+ author: "Juan Pedro Bolivar Puente ",
+ description: "",
+ forums: "",
+ wiki: ""
+ };
+
+ Script.property('name', {
+ get: function() {
+ assert(this.__registeredName, "Script must be registered");
+ return this.__registeredName;
+ }
+ });
+
+ Script.prototype.add = function() {
+ var controls, ref3;
+ controls = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ assert(!this._isInit, "Can only add controls in constructor");
+ return (ref3 = this.controls).push.apply(ref3, flatten(controls));
+ };
+
+ Script.prototype.init = catching(function() {
+ var control, i, len, ref3, results;
+ this._isInit = true;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.init(this));
+ }
+ return results;
+ });
+
+ Script.prototype.shutdown = catching(function() {
+ var control, i, len, ref3;
+ ref3 = this.controls;
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ control.shutdown(this);
+ }
+ return delete this._isInit;
+ });
+
+ function Script() {
+ this.controls = [];
+ }
+
+ Script.prototype.mixxx = {
+ engine: (typeof engine !== "undefined" && engine !== null ? engine : void 0),
+ midi: (typeof midi !== "undefined" && midi !== null ? midi : void 0),
+ script: (typeof script !== "undefined" && script !== null ? script : void 0)
+ };
+
+ Script.prototype.main = function() {
+ var arg, i, len, ref3, results;
+ ref3 = process.argv;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ arg = ref3[i];
+ if (arg === '-h' || arg === '--help') {
+ console.info(this.help());
+ break;
+ }
+ if (arg === '-g' || arg === '--generate-config') {
+ console.info(this.config());
+ break;
+ } else {
+ results.push(void 0);
+ }
+ }
+ return results;
+ };
+
+ Script.prototype.help = function() {
+ return "Mixxx Controller Script\n=======================\n\nName: " + this.info.name + "\nAuthor: " + this.info.author + "\nDescription: " + this.info.description + "\nForums: " + this.info.description + "\n\nUsage\n-----\n1. Generate Mixxx config:\n coffee " + this.name + ".coffee -g > " + this.name + ".xml\n\n2. Generate Mixxx script:\n coffee -c " + this.name + ".coffee";
+ };
+
+ Script.prototype.config = function() {
+ return "\n\n" + (indent(1)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.name)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.author)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.description)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.wiki)) + "\n" + (indent(2)) + "" + (xmlEscape(this.info.forums)) + "\n" + (indent(1)) + "\n" + (indent(1)) + "\n" + (indent(2)) + "\n" + (indent(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "\n" + (indent(2)) + "\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "\n" + (indent(1)) + "\n";
+ };
+
+ Script.prototype.configInputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configInputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype.configOutputs = function(depth) {
+ var control;
+ return ((function() {
+ var i, len, ref3, results;
+ ref3 = this.controls;
+ results = [];
+ for (i = 0, len = ref3.length; i < len; i++) {
+ control = ref3[i];
+ results.push(control.configOutputs(depth, this));
+ }
+ return results;
+ }).call(this)).filter(function(x) {
+ return x;
+ }).join('\n');
+ };
+
+ Script.prototype._nextCallbackId = 1;
+
+ Script.prototype.registerHandler = function(callback, id) {
+ var handlerName;
+ if (id == null) {
+ id = void 0;
+ }
+ id || (id = this._nextCallbackId++);
+ handlerName = "__handle_" + id;
+ assert(!this[handlerName], "Handlers can be registered only once (" + handlerName + ")");
+ this[handlerName] = callback;
+ return this.handlerKey(id);
+ };
+
+ Script.prototype.handlerKey = function(id) {
+ if (id == null) {
+ id = void 0;
+ }
+ if (id == null) {
+ id = this._nextCallbackId - 1;
+ }
+ return this.name + ".__handle_" + id;
+ };
+
+ return Script;
+
+})();
+
+
+}).call(this,require('_process'))
+},{"./console":18,"./control":19,"./util":22,"_process":12,"heterarchy":13,"path":11,"string":15,"underscore":16}],21:[function(require,module,exports){
+var binaryT, centeredT, defaultT, identityT, linearT, momentaryT,
+ slice = [].slice;
+
+exports.identity = function(v) {
+ return v;
+};
+
+exports.identity.inverse = exports.identity;
+
+exports.momentary = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.momentary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.binary = function(v, oldv) {
+ if (v > 0) {
+ return !oldv;
+ } else {
+ return null;
+ }
+};
+
+exports.binary.inverse = function(v) {
+ if (v > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+};
+
+exports.linear = function(v, min, max) {
+ return min + v * (max - min);
+};
+
+exports.linear.inverse = function(v, min, max) {
+ return (v - min) / (max - min);
+};
+
+exports.centered = function(v, min, center, max) {
+ if (v < .5) {
+ return linear(v * 2, min, center);
+ } else {
+ return linear((v - .5) * 2, center, max);
+ }
+};
+
+exports.centered.inverse = function(v, min, center, max) {
+ if (v < center) {
+ return 0.5 * linear.inverse(v, min, center);
+ } else {
+ return 0.5 + 0.5 * linear.inverse(v, center, max);
+ }
+};
+
+exports.transform = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformI = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.value].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.transformB = function() {
+ var args, f, result;
+ f = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ result = function(ev, oldv) {
+ return f.apply(null, [ev.pressed / 127.0].concat(slice.call(args), [oldv]));
+ };
+ result.inverse = function(v) {
+ return 127 * f.inverse.apply(f, [v].concat(slice.call(args)));
+ };
+ return result;
+};
+
+exports.identityT = identityT = exports.transformI(exports.identity);
+
+exports.momentaryT = momentaryT = exports.transformB(exports.momentary);
+
+exports.binaryT = binaryT = exports.transformB(exports.binary);
+
+exports.linearT = linearT = function() {
+ return exports.transform.apply(exports, [exports.linear].concat(slice.call(arguments)));
+};
+
+exports.centeredT = centeredT = function() {
+ return exports.transform.apply(exports, [exports.centered].concat(slice.call(arguments)));
+};
+
+exports.defaultT = defaultT = linearT(0.0, 1.0);
+
+exports.mappings = {
+ "beatloop_0.0625_activate": momentaryT,
+ "beatloop_0.0625_toggle": momentaryT,
+ "beatloop_0.125_activate": momentaryT,
+ "beatloop_0.125_toggle": momentaryT,
+ "beatloop_0.5_activate": momentaryT,
+ "beatloop_0.5_toggle": momentaryT,
+ "beatlooproll_0.0625_activate": momentaryT,
+ "beatlooproll_0.125_activate": momentaryT,
+ "beatlooproll_0.5_activate": momentaryT,
+ back: momentaryT,
+ balance: linearT(-1.0, 1.0),
+ beatloop_16_activate: momentaryT,
+ beatloop_16_toggle: momentaryT,
+ beatloop_1_activate: momentaryT,
+ beatloop_1_toggle: momentaryT,
+ beatloop_2_activate: momentaryT,
+ beatloop_2_toggle: momentaryT,
+ beatloop_32_activate: momentaryT,
+ beatloop_32_toggle: momentaryT,
+ beatloop_4_activate: momentaryT,
+ beatloop_4_toggle: momentaryT,
+ beatloop_8_activate: momentaryT,
+ beatloop_8_toggle: momentaryT,
+ beatlooproll_16_activate: momentaryT,
+ beatlooproll_1_activate: momentaryT,
+ beatlooproll_2_activate: momentaryT,
+ beatlooproll_32_activate: momentaryT,
+ beatlooproll_4_activate: momentaryT,
+ beatlooproll_8_activate: momentaryT,
+ beatloop_double: momentaryT,
+ beatloop_halve: momentaryT,
+ beatjump_4_forward: momentaryT,
+ beatjump_4_backward: momentaryT,
+ beatjump_1_forward: momentaryT,
+ beatjump_1_backward: momentaryT,
+ beats_translate_curpos: momentaryT,
+ beatsync: momentaryT,
+ beatsync_tempo: momentaryT,
+ crossfader: linearT(-1.0, 1.0),
+ cue_default: momentaryT,
+ eject: momentaryT,
+ enabled: binaryT,
+ filterHigh: centeredT(0.0, 1.0, 4.0),
+ filterHighKill: binaryT,
+ filterLow: centeredT(0.0, 1.0, 4.0),
+ filterLowKill: binaryT,
+ filterMid: centeredT(0.0, 1.0, 4.0),
+ filterMidKill: binaryT,
+ fwd: momentaryT,
+ headMix: centeredT(-1.0, 1.0),
+ headVolume: centeredT(0.0, 1.0, 5.0),
+ hotcue_1_activate: momentaryT,
+ hotcue_1_clear: momentaryT,
+ hotcue_2_activate: momentaryT,
+ hotcue_2_clear: momentaryT,
+ hotcue_3_activate: momentaryT,
+ hotcue_3_clear: momentaryT,
+ hotcue_4_activate: momentaryT,
+ hotcue_4_clear: momentaryT,
+ hotcue_5_activate: momentaryT,
+ hotcue_5_clear: momentaryT,
+ hotcue_6_activate: momentaryT,
+ hotcue_6_clear: momentaryT,
+ hotcue_7_activate: momentaryT,
+ hotcue_7_clear: momentaryT,
+ jog: identityT,
+ keylock: binaryT,
+ lfoDelay: linearT(50.0, 10000.0),
+ lfoDepth: defaultT,
+ lfoPeriod: linearT(50000.0, 2000000.0),
+ LoadSelectedTrack: momentaryT,
+ loop_double: momentaryT,
+ loop_enabled: binaryT,
+ loop_end_position: linearT,
+ loop_halve: momentaryT,
+ loop_in: momentaryT,
+ loop_out: momentaryT,
+ loop_start_position: linearT,
+ play: binaryT,
+ playposition: linearT(0.0, 1.0),
+ plf: binaryT,
+ pregain: centeredT(0.0, 1.0, 4.0),
+ pregain_toggle: binaryT,
+ rate: linearT(-1.0, 1.0),
+ rate_temp_down: momentaryT,
+ rate_temp_down_small: momentaryT,
+ rate_temp_up: momentaryT,
+ rate_temp_up_small: momentaryT,
+ reverse: binaryT,
+ scratch2: linearT(-3.0, 3.0),
+ scratch2_enable: binaryT,
+ SelectNextPlaylist: momentaryT,
+ SelectNextTrack: momentaryT,
+ SelectPrevPlaylist: momentaryT,
+ SelectPrevTrack: momentaryT,
+ SelectTrackKnob: identityT,
+ slip_enabled: binaryT,
+ super1: linearT(0.0, 10.0),
+ talkover: binaryT,
+ ToggleSelectedSidebarItem: momentaryT,
+ volume: defaultT,
+ VuMeter: defaultT,
+ VuMeterL: defaultT,
+ VuMeterR: defaultT,
+ wheel: linearT(-3.0, 3.0)
+};
+
+
+},{}],22:[function(require,module,exports){
+Function.prototype.property = function(prop, desc) {
+ if (desc instanceof Function) {
+ desc = {
+ get: desc
+ };
+ }
+ return Object.defineProperty(this.prototype, prop, desc);
+};
+
+Number.prototype.clamp = function(min, max) {
+ return Math.min(Math.max(this, min), max);
+};
+
+Number.prototype.sign = function() {
+ if (this < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+};
+
+Array.prototype.equals = function(other) {
+ return this.length === other.length && this.every(function(elem, i) {
+ return elem === other[i];
+ });
+};
+
+exports.copy = function(a, b) {
+ var k, v;
+ if (b == null) {
+ b = {};
+ }
+ for (k in a) {
+ v = a[k];
+ b[k] = v;
+ }
+ return b;
+};
+
+exports.catching = function(f) {
+ return function() {
+ var err, error1;
+ try {
+ return f.apply(this, arguments);
+ } catch (error1) {
+ err = error1;
+ return console.log("ERROR: " + err);
+ }
+ };
+};
+
+exports.assert = function(value, error) {
+ if (error == null) {
+ error = void 0;
+ }
+ if (!value) {
+ throw new Error(error != null ? error : "Assertion failed");
+ }
+};
+
+exports.xmlEscape = function(str) {
+ var ref;
+ return (ref = str != null ? str.replace('&', '&').replace('"', '"').replace('>', '>').replace('<', '<') : void 0) != null ? ref : '';
+};
+
+exports.indent = function(depth) {
+ return Array(depth * 4).join(" ");
+};
+
+exports.hexStr = function(number) {
+ return "0x" + (number.toString(16));
+};
+
+exports.xmlTag = function(str, value, indent) {
+ if (indent == null) {
+ indent = 0;
+ }
+ if (value != null) {
+ return (exports.indent(indent)) + "<" + str + ">" + value + "" + str + ">";
+ } else {
+ return "";
+ }
+};
+
+exports.joinLn = function(lines) {
+ return lines.filter(function(x) {
+ return x;
+ }).join('\n');
+};
+
+exports.factory = function(Klass) {
+ return function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Klass, arguments, function(){});
+ };
+};
+
+
+},{}],23:[function(require,module,exports){
+var events, factory, util,
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ hasProp = {}.hasOwnProperty,
+ slice = [].slice;
+
+events = require('events');
+
+util = require('./util');
+
+factory = util.factory;
+
+exports.Value = (function(superClass) {
+ extend(Value, superClass);
+
+ function Value(arg) {
+ var initial;
+ initial = (arg != null ? arg : {}).initial;
+ Value.__super__.constructor.apply(this, arguments);
+ this.setMaxListeners(0);
+ if (initial != null) {
+ this.value = initial;
+ }
+ }
+
+ Value.property('value', {
+ get: function() {
+ return this._value;
+ },
+ set: function(newValue) {
+ return this.setValue(newValue);
+ }
+ });
+
+ Value.prototype.setValue = function(newValue) {
+ if (this._value !== newValue) {
+ this._value = newValue;
+ this.emit('value', newValue);
+ }
+ return this._value;
+ };
+
+ return Value;
+
+})(events.EventEmitter);
+
+exports.value = factory(exports.Value);
+
+exports.Const = (function() {
+ Const.prototype.value = void 0;
+
+ function Const(initial) {
+ if (initial == null) {
+ initial = void 0;
+ }
+ this.value = initial;
+ }
+
+ Const.prototype.on = function() {};
+
+ Const.prototype.addListener = function() {};
+
+ Const.prototype.removeListener = function() {};
+
+ Const.prototype.listeners = function() {
+ return [];
+ };
+
+ return Const;
+
+})();
+
+exports["const"] = factory(exports.Const);
+
+exports.Reduce = (function(superClass) {
+ extend(Reduce, superClass);
+
+ function Reduce() {
+ var i, len, reduced, reducer, ref, v;
+ reducer = arguments[0], reduced = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ this.reducer = reducer;
+ this.reduced = reduced;
+ Reduce.__super__.constructor.call(this);
+ ref = this.reduced;
+ for (i = 0, len = ref.length; i < len; i++) {
+ v = ref[i];
+ v.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ }
+ this.update();
+ }
+
+ Reduce.prototype.update = function() {
+ return this.value = this.reduced.reduce((function(_this) {
+ return function(a, b) {
+ return exports["const"](_this.reducer(a.value, b.value));
+ };
+ })(this)).value;
+ };
+
+ return Reduce;
+
+})(exports.Value);
+
+exports.reduce = factory(exports.Reduce);
+
+exports.and = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a && b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.or = function() {
+ return exports.reduce.apply(exports, [(function(a, b) {
+ return a || b;
+ })].concat(slice.call(arguments)));
+};
+
+exports.Transform = (function(superClass) {
+ extend(Transform, superClass);
+
+ function Transform(transformer, transformed) {
+ this.transformer = transformer;
+ this.transformed = transformed;
+ Transform.__super__.constructor.call(this);
+ this.transformed.on('value', (function(_this) {
+ return function() {
+ return _this.update();
+ };
+ })(this));
+ this.update();
+ }
+
+ Transform.prototype.update = function() {
+ return this.value = this.transformer(this.transformed.value);
+ };
+
+ return Transform;
+
+})(exports.Value);
+
+exports.transform = factory(exports.Transform);
+
+exports.not = function() {
+ return exports.transform.apply(exports, [(function(a) {
+ return !a;
+ })].concat(slice.call(arguments)));
+};
+
+
+},{"./util":22,"events":10}]},{},[1]);
+
+novation_twitch = require('/home/raskolnikov/dev/mixco/script/novation_twitch.mixco').novation_twitch;
+/* End of Mixco generated script */
\ No newline at end of file
diff --git a/res/controllers/novation_twitch.mixco.output.midi.xml b/res/controllers/novation_twitch.mixco.output.midi.xml
new file mode 100644
index 000000000000..ed372f06afe6
--- /dev/null
+++ b/res/controllers/novation_twitch.mixco.output.midi.xml
@@ -0,0 +1,5159 @@
+
+
+
+ Novation Twitch
+ Juan Pedro Bolivar Puente <raskolnikov@gnu.org>
+ Controller mapping for Novation Twitch (in basic mode).
+ https://sinusoid.es/mixco/script/korg_nanokontrol2.mixco.html
+ https://github.com/arximboldi/mixco/issues
+
+
+
+
+
+
+
+ [Master]
+ crossfader
+ 0xb7
+ 0x8
+
+
+
+
+
+ [Microphone]
+ pregain
+ 0xbb
+ 0x3
+
+
+
+
+
+ [Microphone]
+ pregain
+ 0xbb
+ 0x7
+
+
+
+
+
+ [Microphone]
+ pregain
+ 0xbb
+ 0xb
+
+
+
+
+
+ [Microphone]
+ pregain
+ 0xbb
+ 0xf
+
+
+
+
+
+ [Microphone]
+ pregain
+ 0xbb
+ 0x13
+
+
+
+
+
+ [Microphone]
+ talkover
+ 0x9b
+ 0x23
+
+
+
+
+
+ [Microphone]
+ talkover
+ 0x8b
+ 0x23
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xbb
+ 0x0
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xbb
+ 0x4
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xbb
+ 0x8
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xbb
+ 0xc
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ mix
+ 0xbb
+ 0x10
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xbb_x1
+ 0xbb
+ 0x1
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xbb_x1
+ 0xbb
+ 0x5
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xbb_x1
+ 0xbb
+ 0x9
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xbb_x1
+ 0xbb
+ 0xd
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xbb_x1
+ 0xbb
+ 0x11
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ chain_selector
+ 0xbb
+ 0x2
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ chain_selector
+ 0xbb
+ 0x6
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ chain_selector
+ 0xbb
+ 0xa
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ chain_selector
+ 0xbb
+ 0xe
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ chain_selector
+ 0xbb
+ 0x12
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ enabled
+ 0x9b
+ 0x22
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ enabled
+ 0x8b
+ 0x22
+
+
+
+
+
+ [Playlist]
+ SelectPrevPlaylist
+ 0x97
+ 0x54
+
+
+
+
+
+ [Playlist]
+ SelectPrevPlaylist
+ 0x87
+ 0x54
+
+
+
+
+
+ [Playlist]
+ SelectNextPlaylist
+ 0x97
+ 0x56
+
+
+
+
+
+ [Playlist]
+ SelectNextPlaylist
+ 0x87
+ 0x56
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x55
+ 0x97
+ 0x55
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x55
+ 0x87
+ 0x55
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x55
+ 0xb7
+ 0x55
+
+
+
+
+
+ [Master]
+ maximize_library
+ 0x97
+ 0x50
+
+
+
+
+
+ [Master]
+ maximize_library
+ 0x87
+ 0x50
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x51
+ 0x97
+ 0x51
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x51
+ 0x87
+ 0x51
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_xa
+ 0x97
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_xa
+ 0x87
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_xa
+ 0x99
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_xa
+ 0x89
+ 0xa
+
+
+
+
+
+ [Channel1]
+ volume
+ 0xb7
+ 0x7
+
+
+
+
+
+ [Channel1]
+ volume
+ 0xb9
+ 0x7
+
+
+
+
+
+ [Channel1]
+ filterLow
+ 0xb7
+ 0x46
+
+
+
+
+
+ [Channel1]
+ filterLow
+ 0xb9
+ 0x46
+
+
+
+
+
+ [Channel1]
+ filterMid
+ 0xb7
+ 0x47
+
+
+
+
+
+ [Channel1]
+ filterMid
+ 0xb9
+ 0x47
+
+
+
+
+
+ [Channel1]
+ filterHigh
+ 0xb7
+ 0x48
+
+
+
+
+
+ [Channel1]
+ filterHigh
+ 0xb9
+ 0x48
+
+
+
+
+
+ [Channel1]
+ pregain
+ 0xb7
+ 0x9
+
+
+
+
+
+ [Channel1]
+ pregain
+ 0xb9
+ 0x9
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x6
+ 0xb7
+ 0x6
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x6
+ 0xb9
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x97
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x87
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x99
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x89
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x97
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x87
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x99
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel1]]
+ enabled
+ 0x89
+ 0xd
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel1]_enable
+ 0x9b
+ 0x20
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel1]_enable
+ 0x8b
+ 0x20
+
+
+
+
+
+ [Channel1]
+ LoadSelectedTrack
+ 0x97
+ 0x52
+
+
+
+
+
+ [Channel1]
+ LoadSelectedTrack
+ 0x87
+ 0x52
+
+
+
+
+
+ [Channel1]
+ play
+ 0x97
+ 0x17
+
+
+
+
+
+ [Channel1]
+ play
+ 0x87
+ 0x17
+
+
+
+
+
+ [Channel1]
+ play
+ 0x99
+ 0x17
+
+
+
+
+
+ [Channel1]
+ play
+ 0x89
+ 0x17
+
+
+
+
+
+ [Channel1]
+ cue_default
+ 0x97
+ 0x16
+
+
+
+
+
+ [Channel1]
+ cue_default
+ 0x87
+ 0x16
+
+
+
+
+
+ [Channel1]
+ reverse
+ 0x99
+ 0x16
+
+
+
+
+
+ [Channel1]
+ reverse
+ 0x89
+ 0x16
+
+
+
+
+
+ [Channel1]
+ keylock
+ 0x97
+ 0x12
+
+
+
+
+
+ [Channel1]
+ keylock
+ 0x87
+ 0x12
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x99_x12
+ 0x99
+ 0x12
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x99_x12
+ 0x89
+ 0x12
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x97
+ 0x13
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x87
+ 0x13
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x99
+ 0x13
+
+
+
+
+
+ [Channel1]
+ sync_enabled
+ 0x89
+ 0x13
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x97
+ 0x11
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x87
+ 0x11
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x99
+ 0x11
+
+
+
+
+
+ [Channel1]
+ beats_translate_curpos
+ 0x89
+ 0x11
+
+
+
+
+
+ [Channel1]
+ quantize
+ 0x97
+ 0x10
+
+
+
+
+
+ [Channel1]
+ quantize
+ 0x87
+ 0x10
+
+
+
+
+
+ [Channel1]
+ quantize
+ 0x99
+ 0x10
+
+
+
+
+
+ [Channel1]
+ quantize
+ 0x89
+ 0x10
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x3
+ 0x97
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x3
+ 0x87
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x3
+ 0x99
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x3
+ 0x89
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x3
+ 0xb7
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x3
+ 0xb9
+ 0x3
+
+
+
+
+
+ [Channel1]
+ playposition
+ 0xb7
+ 0x34
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb7_x35
+ 0xb7
+ 0x35
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb9_x35
+ 0xb9
+ 0x35
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x99_x47
+ 0x99
+ 0x47
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x99_x47
+ 0x89
+ 0x47
+
+
+
+
+
+ [Channel1]
+ hotcue_1_activate
+ 0x97
+ 0x60
+
+
+
+
+
+ [Channel1]
+ hotcue_1_activate
+ 0x87
+ 0x60
+
+
+
+
+
+ [Channel1]
+ hotcue_1_clear
+ 0x99
+ 0x60
+
+
+
+
+
+ [Channel1]
+ hotcue_1_clear
+ 0x89
+ 0x60
+
+
+
+
+
+ [Channel1]
+ hotcue_2_activate
+ 0x97
+ 0x61
+
+
+
+
+
+ [Channel1]
+ hotcue_2_activate
+ 0x87
+ 0x61
+
+
+
+
+
+ [Channel1]
+ hotcue_2_clear
+ 0x99
+ 0x61
+
+
+
+
+
+ [Channel1]
+ hotcue_2_clear
+ 0x89
+ 0x61
+
+
+
+
+
+ [Channel1]
+ hotcue_3_activate
+ 0x97
+ 0x62
+
+
+
+
+
+ [Channel1]
+ hotcue_3_activate
+ 0x87
+ 0x62
+
+
+
+
+
+ [Channel1]
+ hotcue_3_clear
+ 0x99
+ 0x62
+
+
+
+
+
+ [Channel1]
+ hotcue_3_clear
+ 0x89
+ 0x62
+
+
+
+
+
+ [Channel1]
+ hotcue_4_activate
+ 0x97
+ 0x63
+
+
+
+
+
+ [Channel1]
+ hotcue_4_activate
+ 0x87
+ 0x63
+
+
+
+
+
+ [Channel1]
+ hotcue_4_clear
+ 0x99
+ 0x63
+
+
+
+
+
+ [Channel1]
+ hotcue_4_clear
+ 0x89
+ 0x63
+
+
+
+
+
+ [Channel1]
+ hotcue_5_activate
+ 0x97
+ 0x64
+
+
+
+
+
+ [Channel1]
+ hotcue_5_activate
+ 0x87
+ 0x64
+
+
+
+
+
+ [Channel1]
+ hotcue_5_clear
+ 0x99
+ 0x64
+
+
+
+
+
+ [Channel1]
+ hotcue_5_clear
+ 0x89
+ 0x64
+
+
+
+
+
+ [Channel1]
+ hotcue_6_activate
+ 0x97
+ 0x65
+
+
+
+
+
+ [Channel1]
+ hotcue_6_activate
+ 0x87
+ 0x65
+
+
+
+
+
+ [Channel1]
+ hotcue_6_clear
+ 0x99
+ 0x65
+
+
+
+
+
+ [Channel1]
+ hotcue_6_clear
+ 0x89
+ 0x65
+
+
+
+
+
+ [Channel1]
+ hotcue_7_activate
+ 0x97
+ 0x66
+
+
+
+
+
+ [Channel1]
+ hotcue_7_activate
+ 0x87
+ 0x66
+
+
+
+
+
+ [Channel1]
+ hotcue_7_clear
+ 0x99
+ 0x66
+
+
+
+
+
+ [Channel1]
+ hotcue_7_clear
+ 0x89
+ 0x66
+
+
+
+
+
+ [Channel1]
+ hotcue_8_activate
+ 0x97
+ 0x67
+
+
+
+
+
+ [Channel1]
+ hotcue_8_activate
+ 0x87
+ 0x67
+
+
+
+
+
+ [Channel1]
+ hotcue_8_clear
+ 0x99
+ 0x67
+
+
+
+
+
+ [Channel1]
+ hotcue_8_clear
+ 0x89
+ 0x67
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x97
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x87
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x99
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x89
+ 0x68
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x97
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x87
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x99
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x89
+ 0x69
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x97
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x87
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x99
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x89
+ 0x6a
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x97
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x87
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x99
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x89
+ 0x6b
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6c
+ 0x97
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6c
+ 0x87
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6c
+ 0x99
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6c
+ 0x89
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6d
+ 0x97
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6d
+ 0x87
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6d
+ 0x99
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6d
+ 0x89
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6e
+ 0x97
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6e
+ 0x87
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6e
+ 0x99
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6e
+ 0x89
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6f
+ 0x97
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6f
+ 0x87
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6f
+ 0x99
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x97_x6f
+ 0x89
+ 0x6f
+
+
+
+
+
+ [Channel1]
+ beatloop_0.5_toggle
+ 0x97
+ 0x70
+
+
+
+
+
+ [Channel1]
+ beatloop_0.5_toggle
+ 0x87
+ 0x70
+
+
+
+
+
+ [Channel1]
+ beatloop_1_toggle
+ 0x97
+ 0x71
+
+
+
+
+
+ [Channel1]
+ beatloop_1_toggle
+ 0x87
+ 0x71
+
+
+
+
+
+ [Channel1]
+ beatloop_2_toggle
+ 0x97
+ 0x72
+
+
+
+
+
+ [Channel1]
+ beatloop_2_toggle
+ 0x87
+ 0x72
+
+
+
+
+
+ [Channel1]
+ beatloop_4_toggle
+ 0x97
+ 0x73
+
+
+
+
+
+ [Channel1]
+ beatloop_4_toggle
+ 0x87
+ 0x73
+
+
+
+
+
+ [Channel1]
+ beatloop_8_toggle
+ 0x97
+ 0x74
+
+
+
+
+
+ [Channel1]
+ beatloop_8_toggle
+ 0x87
+ 0x74
+
+
+
+
+
+ [Channel1]
+ beatloop_16_toggle
+ 0x97
+ 0x75
+
+
+
+
+
+ [Channel1]
+ beatloop_16_toggle
+ 0x87
+ 0x75
+
+
+
+
+
+ [Channel1]
+ beatloop_32_toggle
+ 0x97
+ 0x76
+
+
+
+
+
+ [Channel1]
+ beatloop_32_toggle
+ 0x87
+ 0x76
+
+
+
+
+
+ [Channel1]
+ beatloop_64_toggle
+ 0x97
+ 0x77
+
+
+
+
+
+ [Channel1]
+ beatloop_64_toggle
+ 0x87
+ 0x77
+
+
+
+
+
+ [Channel1]
+ beatloop_0.03125_toggle
+ 0x99
+ 0x70
+
+
+
+
+
+ [Channel1]
+ beatloop_0.03125_toggle
+ 0x89
+ 0x70
+
+
+
+
+
+ [Channel1]
+ beatloop_0.0625_toggle
+ 0x99
+ 0x71
+
+
+
+
+
+ [Channel1]
+ beatloop_0.0625_toggle
+ 0x89
+ 0x71
+
+
+
+
+
+ [Channel1]
+ beatloop_0.125_toggle
+ 0x99
+ 0x72
+
+
+
+
+
+ [Channel1]
+ beatloop_0.125_toggle
+ 0x89
+ 0x72
+
+
+
+
+
+ [Channel1]
+ beatloop_0.25_toggle
+ 0x99
+ 0x73
+
+
+
+
+
+ [Channel1]
+ beatloop_0.25_toggle
+ 0x89
+ 0x73
+
+
+
+
+
+ [Channel1]
+ beatloop_0.5_toggle
+ 0x99
+ 0x74
+
+
+
+
+
+ [Channel1]
+ beatloop_0.5_toggle
+ 0x89
+ 0x74
+
+
+
+
+
+ [Channel1]
+ beatloop_1_toggle
+ 0x99
+ 0x75
+
+
+
+
+
+ [Channel1]
+ beatloop_1_toggle
+ 0x89
+ 0x75
+
+
+
+
+
+ [Channel1]
+ beatloop_2_toggle
+ 0x99
+ 0x76
+
+
+
+
+
+ [Channel1]
+ beatloop_2_toggle
+ 0x89
+ 0x76
+
+
+
+
+
+ [Channel1]
+ beatloop_4_toggle
+ 0x99
+ 0x77
+
+
+
+
+
+ [Channel1]
+ beatloop_4_toggle
+ 0x89
+ 0x77
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.03125_activate
+ 0x97
+ 0x78
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.03125_activate
+ 0x87
+ 0x78
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.0625_activate
+ 0x97
+ 0x79
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.0625_activate
+ 0x87
+ 0x79
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.125_activate
+ 0x97
+ 0x7a
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.125_activate
+ 0x87
+ 0x7a
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.25_activate
+ 0x97
+ 0x7b
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.25_activate
+ 0x87
+ 0x7b
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.5_activate
+ 0x97
+ 0x7c
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.5_activate
+ 0x87
+ 0x7c
+
+
+
+
+
+ [Channel1]
+ beatlooproll_1_activate
+ 0x97
+ 0x7d
+
+
+
+
+
+ [Channel1]
+ beatlooproll_1_activate
+ 0x87
+ 0x7d
+
+
+
+
+
+ [Channel1]
+ beatlooproll_2_activate
+ 0x97
+ 0x7e
+
+
+
+
+
+ [Channel1]
+ beatlooproll_2_activate
+ 0x87
+ 0x7e
+
+
+
+
+
+ [Channel1]
+ beatlooproll_4_activate
+ 0x97
+ 0x7f
+
+
+
+
+
+ [Channel1]
+ beatlooproll_4_activate
+ 0x87
+ 0x7f
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.5_activate
+ 0x99
+ 0x78
+
+
+
+
+
+ [Channel1]
+ beatlooproll_0.5_activate
+ 0x89
+ 0x78
+
+
+
+
+
+ [Channel1]
+ beatlooproll_1_activate
+ 0x99
+ 0x79
+
+
+
+
+
+ [Channel1]
+ beatlooproll_1_activate
+ 0x89
+ 0x79
+
+
+
+
+
+ [Channel1]
+ beatlooproll_2_activate
+ 0x99
+ 0x7a
+
+
+
+
+
+ [Channel1]
+ beatlooproll_2_activate
+ 0x89
+ 0x7a
+
+
+
+
+
+ [Channel1]
+ beatlooproll_4_activate
+ 0x99
+ 0x7b
+
+
+
+
+
+ [Channel1]
+ beatlooproll_4_activate
+ 0x89
+ 0x7b
+
+
+
+
+
+ [Channel1]
+ beatlooproll_8_activate
+ 0x99
+ 0x7c
+
+
+
+
+
+ [Channel1]
+ beatlooproll_8_activate
+ 0x89
+ 0x7c
+
+
+
+
+
+ [Channel1]
+ beatlooproll_16_activate
+ 0x99
+ 0x7d
+
+
+
+
+
+ [Channel1]
+ beatlooproll_16_activate
+ 0x89
+ 0x7d
+
+
+
+
+
+ [Channel1]
+ beatlooproll_32_activate
+ 0x99
+ 0x7e
+
+
+
+
+
+ [Channel1]
+ beatlooproll_32_activate
+ 0x89
+ 0x7e
+
+
+
+
+
+ [Channel1]
+ beatlooproll_64_activate
+ 0x99
+ 0x7f
+
+
+
+
+
+ [Channel1]
+ beatlooproll_64_activate
+ 0x89
+ 0x7f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_xa
+ 0x98
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_xa
+ 0x88
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_xa
+ 0x9a
+ 0xa
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_xa
+ 0x8a
+ 0xa
+
+
+
+
+
+ [Channel2]
+ volume
+ 0xb8
+ 0x7
+
+
+
+
+
+ [Channel2]
+ volume
+ 0xba
+ 0x7
+
+
+
+
+
+ [Channel2]
+ filterLow
+ 0xb8
+ 0x46
+
+
+
+
+
+ [Channel2]
+ filterLow
+ 0xba
+ 0x46
+
+
+
+
+
+ [Channel2]
+ filterMid
+ 0xb8
+ 0x47
+
+
+
+
+
+ [Channel2]
+ filterMid
+ 0xba
+ 0x47
+
+
+
+
+
+ [Channel2]
+ filterHigh
+ 0xb8
+ 0x48
+
+
+
+
+
+ [Channel2]
+ filterHigh
+ 0xba
+ 0x48
+
+
+
+
+
+ [Channel2]
+ pregain
+ 0xb8
+ 0x9
+
+
+
+
+
+ [Channel2]
+ pregain
+ 0xba
+ 0x9
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb8_x6
+ 0xb8
+ 0x6
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb8_x6
+ 0xba
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x98
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x88
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x9a
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x8a
+ 0x6
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x98
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x88
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x9a
+ 0xd
+
+
+
+
+
+ [QuickEffectRack1_[Channel2]]
+ enabled
+ 0x8a
+ 0xd
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel2]_enable
+ 0x9b
+ 0x21
+
+
+
+
+
+ [EffectRack1_EffectUnit1]
+ group_[Channel2]_enable
+ 0x8b
+ 0x21
+
+
+
+
+
+ [Channel2]
+ LoadSelectedTrack
+ 0x97
+ 0x53
+
+
+
+
+
+ [Channel2]
+ LoadSelectedTrack
+ 0x87
+ 0x53
+
+
+
+
+
+ [Channel2]
+ play
+ 0x98
+ 0x17
+
+
+
+
+
+ [Channel2]
+ play
+ 0x88
+ 0x17
+
+
+
+
+
+ [Channel2]
+ play
+ 0x9a
+ 0x17
+
+
+
+
+
+ [Channel2]
+ play
+ 0x8a
+ 0x17
+
+
+
+
+
+ [Channel2]
+ cue_default
+ 0x98
+ 0x16
+
+
+
+
+
+ [Channel2]
+ cue_default
+ 0x88
+ 0x16
+
+
+
+
+
+ [Channel2]
+ reverse
+ 0x9a
+ 0x16
+
+
+
+
+
+ [Channel2]
+ reverse
+ 0x8a
+ 0x16
+
+
+
+
+
+ [Channel2]
+ keylock
+ 0x98
+ 0x12
+
+
+
+
+
+ [Channel2]
+ keylock
+ 0x88
+ 0x12
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x9a_x12
+ 0x9a
+ 0x12
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x9a_x12
+ 0x8a
+ 0x12
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x98
+ 0x13
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x88
+ 0x13
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x9a
+ 0x13
+
+
+
+
+
+ [Channel2]
+ sync_enabled
+ 0x8a
+ 0x13
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x98
+ 0x11
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x88
+ 0x11
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x9a
+ 0x11
+
+
+
+
+
+ [Channel2]
+ beats_translate_curpos
+ 0x8a
+ 0x11
+
+
+
+
+
+ [Channel2]
+ quantize
+ 0x98
+ 0x10
+
+
+
+
+
+ [Channel2]
+ quantize
+ 0x88
+ 0x10
+
+
+
+
+
+ [Channel2]
+ quantize
+ 0x9a
+ 0x10
+
+
+
+
+
+ [Channel2]
+ quantize
+ 0x8a
+ 0x10
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x3
+ 0x98
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x3
+ 0x88
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x3
+ 0x9a
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x3
+ 0x8a
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb8_x3
+ 0xb8
+ 0x3
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb8_x3
+ 0xba
+ 0x3
+
+
+
+
+
+ [Channel2]
+ playposition
+ 0xb8
+ 0x34
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xb8_x35
+ 0xb8
+ 0x35
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_xba_x35
+ 0xba
+ 0x35
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x9a_x47
+ 0x9a
+ 0x47
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x9a_x47
+ 0x8a
+ 0x47
+
+
+
+
+
+ [Channel2]
+ hotcue_1_activate
+ 0x98
+ 0x60
+
+
+
+
+
+ [Channel2]
+ hotcue_1_activate
+ 0x88
+ 0x60
+
+
+
+
+
+ [Channel2]
+ hotcue_1_clear
+ 0x9a
+ 0x60
+
+
+
+
+
+ [Channel2]
+ hotcue_1_clear
+ 0x8a
+ 0x60
+
+
+
+
+
+ [Channel2]
+ hotcue_2_activate
+ 0x98
+ 0x61
+
+
+
+
+
+ [Channel2]
+ hotcue_2_activate
+ 0x88
+ 0x61
+
+
+
+
+
+ [Channel2]
+ hotcue_2_clear
+ 0x9a
+ 0x61
+
+
+
+
+
+ [Channel2]
+ hotcue_2_clear
+ 0x8a
+ 0x61
+
+
+
+
+
+ [Channel2]
+ hotcue_3_activate
+ 0x98
+ 0x62
+
+
+
+
+
+ [Channel2]
+ hotcue_3_activate
+ 0x88
+ 0x62
+
+
+
+
+
+ [Channel2]
+ hotcue_3_clear
+ 0x9a
+ 0x62
+
+
+
+
+
+ [Channel2]
+ hotcue_3_clear
+ 0x8a
+ 0x62
+
+
+
+
+
+ [Channel2]
+ hotcue_4_activate
+ 0x98
+ 0x63
+
+
+
+
+
+ [Channel2]
+ hotcue_4_activate
+ 0x88
+ 0x63
+
+
+
+
+
+ [Channel2]
+ hotcue_4_clear
+ 0x9a
+ 0x63
+
+
+
+
+
+ [Channel2]
+ hotcue_4_clear
+ 0x8a
+ 0x63
+
+
+
+
+
+ [Channel2]
+ hotcue_5_activate
+ 0x98
+ 0x64
+
+
+
+
+
+ [Channel2]
+ hotcue_5_activate
+ 0x88
+ 0x64
+
+
+
+
+
+ [Channel2]
+ hotcue_5_clear
+ 0x9a
+ 0x64
+
+
+
+
+
+ [Channel2]
+ hotcue_5_clear
+ 0x8a
+ 0x64
+
+
+
+
+
+ [Channel2]
+ hotcue_6_activate
+ 0x98
+ 0x65
+
+
+
+
+
+ [Channel2]
+ hotcue_6_activate
+ 0x88
+ 0x65
+
+
+
+
+
+ [Channel2]
+ hotcue_6_clear
+ 0x9a
+ 0x65
+
+
+
+
+
+ [Channel2]
+ hotcue_6_clear
+ 0x8a
+ 0x65
+
+
+
+
+
+ [Channel2]
+ hotcue_7_activate
+ 0x98
+ 0x66
+
+
+
+
+
+ [Channel2]
+ hotcue_7_activate
+ 0x88
+ 0x66
+
+
+
+
+
+ [Channel2]
+ hotcue_7_clear
+ 0x9a
+ 0x66
+
+
+
+
+
+ [Channel2]
+ hotcue_7_clear
+ 0x8a
+ 0x66
+
+
+
+
+
+ [Channel2]
+ hotcue_8_activate
+ 0x98
+ 0x67
+
+
+
+
+
+ [Channel2]
+ hotcue_8_activate
+ 0x88
+ 0x67
+
+
+
+
+
+ [Channel2]
+ hotcue_8_clear
+ 0x9a
+ 0x67
+
+
+
+
+
+ [Channel2]
+ hotcue_8_clear
+ 0x8a
+ 0x67
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x98
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x88
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x9a
+ 0x68
+
+
+
+
+
+ [Sampler1]
+ cue_preview
+ 0x8a
+ 0x68
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x98
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x88
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x9a
+ 0x69
+
+
+
+
+
+ [Sampler2]
+ cue_preview
+ 0x8a
+ 0x69
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x98
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x88
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x9a
+ 0x6a
+
+
+
+
+
+ [Sampler3]
+ cue_preview
+ 0x8a
+ 0x6a
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x98
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x88
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x9a
+ 0x6b
+
+
+
+
+
+ [Sampler4]
+ cue_preview
+ 0x8a
+ 0x6b
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6c
+ 0x98
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6c
+ 0x88
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6c
+ 0x9a
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6c
+ 0x8a
+ 0x6c
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6d
+ 0x98
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6d
+ 0x88
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6d
+ 0x9a
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6d
+ 0x8a
+ 0x6d
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6e
+ 0x98
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6e
+ 0x88
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6e
+ 0x9a
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6e
+ 0x8a
+ 0x6e
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6f
+ 0x98
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6f
+ 0x88
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6f
+ 0x9a
+ 0x6f
+
+
+
+
+
+ [Master]
+ novation_twitch.__handle_x98_x6f
+ 0x8a
+ 0x6f
+
+
+
+
+
+ [Channel2]
+ beatloop_0.5_toggle
+ 0x98
+ 0x70
+
+
+
+
+
+ [Channel2]
+ beatloop_0.5_toggle
+ 0x88
+ 0x70
+
+
+
+
+
+ [Channel2]
+ beatloop_1_toggle
+ 0x98
+ 0x71
+
+
+
+
+
+ [Channel2]
+ beatloop_1_toggle
+ 0x88
+ 0x71
+
+
+
+
+
+ [Channel2]
+ beatloop_2_toggle
+ 0x98
+ 0x72
+
+
+
+
+
+ [Channel2]
+ beatloop_2_toggle
+ 0x88
+ 0x72
+
+
+
+
+
+ [Channel2]
+ beatloop_4_toggle
+ 0x98
+ 0x73
+
+
+
+
+
+ [Channel2]
+ beatloop_4_toggle
+ 0x88
+ 0x73
+
+
+
+
+
+ [Channel2]
+ beatloop_8_toggle
+ 0x98
+ 0x74
+
+
+
+
+
+ [Channel2]
+ beatloop_8_toggle
+ 0x88
+ 0x74
+
+
+
+
+
+ [Channel2]
+ beatloop_16_toggle
+ 0x98
+ 0x75
+
+
+
+
+
+ [Channel2]
+ beatloop_16_toggle
+ 0x88
+ 0x75
+
+
+
+
+
+ [Channel2]
+ beatloop_32_toggle
+ 0x98
+ 0x76
+
+
+
+
+
+ [Channel2]
+ beatloop_32_toggle
+ 0x88
+ 0x76
+
+
+
+
+
+ [Channel2]
+ beatloop_64_toggle
+ 0x98
+ 0x77
+
+
+
+
+
+ [Channel2]
+ beatloop_64_toggle
+ 0x88
+ 0x77
+
+
+
+
+
+ [Channel2]
+ beatloop_0.03125_toggle
+ 0x9a
+ 0x70
+
+
+
+
+
+ [Channel2]
+ beatloop_0.03125_toggle
+ 0x8a
+ 0x70
+
+
+
+
+
+ [Channel2]
+ beatloop_0.0625_toggle
+ 0x9a
+ 0x71
+
+
+
+
+
+ [Channel2]
+ beatloop_0.0625_toggle
+ 0x8a
+ 0x71
+
+
+
+
+
+ [Channel2]
+ beatloop_0.125_toggle
+ 0x9a
+ 0x72
+
+
+
+
+
+ [Channel2]
+ beatloop_0.125_toggle
+ 0x8a
+ 0x72
+
+
+
+
+
+ [Channel2]
+ beatloop_0.25_toggle
+ 0x9a
+ 0x73
+
+
+
+
+
+ [Channel2]
+ beatloop_0.25_toggle
+ 0x8a
+ 0x73
+
+
+
+
+
+ [Channel2]
+ beatloop_0.5_toggle
+ 0x9a
+ 0x74
+
+
+
+
+
+ [Channel2]
+ beatloop_0.5_toggle
+ 0x8a
+ 0x74
+
+
+
+
+
+ [Channel2]
+ beatloop_1_toggle
+ 0x9a
+ 0x75
+
+
+
+
+
+ [Channel2]
+ beatloop_1_toggle
+ 0x8a
+ 0x75
+
+
+
+
+
+ [Channel2]
+ beatloop_2_toggle
+ 0x9a
+ 0x76
+
+
+
+
+
+ [Channel2]
+ beatloop_2_toggle
+ 0x8a
+ 0x76
+
+
+
+
+
+ [Channel2]
+ beatloop_4_toggle
+ 0x9a
+ 0x77
+
+
+
+
+
+ [Channel2]
+ beatloop_4_toggle
+ 0x8a
+ 0x77
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.03125_activate
+ 0x98
+ 0x78
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.03125_activate
+ 0x88
+ 0x78
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.0625_activate
+ 0x98
+ 0x79
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.0625_activate
+ 0x88
+ 0x79
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.125_activate
+ 0x98
+ 0x7a
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.125_activate
+ 0x88
+ 0x7a
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.25_activate
+ 0x98
+ 0x7b
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.25_activate
+ 0x88
+ 0x7b
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.5_activate
+ 0x98
+ 0x7c
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.5_activate
+ 0x88
+ 0x7c
+
+
+
+
+
+ [Channel2]
+ beatlooproll_1_activate
+ 0x98
+ 0x7d
+
+
+
+
+
+ [Channel2]
+ beatlooproll_1_activate
+ 0x88
+ 0x7d
+
+
+
+
+
+ [Channel2]
+ beatlooproll_2_activate
+ 0x98
+ 0x7e
+
+
+
+
+
+ [Channel2]
+ beatlooproll_2_activate
+ 0x88
+ 0x7e
+
+
+
+
+
+ [Channel2]
+ beatlooproll_4_activate
+ 0x98
+ 0x7f
+
+
+
+
+
+ [Channel2]
+ beatlooproll_4_activate
+ 0x88
+ 0x7f
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.5_activate
+ 0x9a
+ 0x78
+
+
+
+
+
+ [Channel2]
+ beatlooproll_0.5_activate
+ 0x8a
+ 0x78
+
+
+
+
+
+ [Channel2]
+ beatlooproll_1_activate
+ 0x9a
+ 0x79
+
+
+
+
+
+ [Channel2]
+ beatlooproll_1_activate
+ 0x8a
+ 0x79
+
+
+
+
+
+ [Channel2]
+ beatlooproll_2_activate
+ 0x9a
+ 0x7a
+
+
+
+
+
+ [Channel2]
+ beatlooproll_2_activate
+ 0x8a
+ 0x7a
+
+
+
+
+
+ [Channel2]
+ beatlooproll_4_activate
+ 0x9a
+ 0x7b
+
+
+
+
+
+ [Channel2]
+ beatlooproll_4_activate
+ 0x8a
+ 0x7b
+
+
+
+
+
+ [Channel2]
+ beatlooproll_8_activate
+ 0x9a
+ 0x7c
+
+
+
+
+
+ [Channel2]
+ beatlooproll_8_activate
+ 0x8a
+ 0x7c
+
+
+
+
+
+ [Channel2]
+ beatlooproll_16_activate
+ 0x9a
+ 0x7d
+
+
+
+
+
+ [Channel2]
+ beatlooproll_16_activate
+ 0x8a
+ 0x7d
+
+
+
+
+
+ [Channel2]
+ beatlooproll_32_activate
+ 0x9a
+ 0x7e
+
+
+
+
+
+ [Channel2]
+ beatlooproll_32_activate
+ 0x8a
+ 0x7e
+
+
+
+
+
+ [Channel2]
+ beatlooproll_64_activate
+ 0x9a
+ 0x7f
+
+
+
+
+
+ [Channel2]
+ beatlooproll_64_activate
+ 0x8a
+ 0x7f
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+