/*
 * File generated with Mixco framework version: 2.0.2
 * More info at: <http://sinusoid.es/mixco>
 */

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<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
require('/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco.litcoffee');
},{"/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco.litcoffee":"/home/raskolnikov/dev/mixco/script/maudio_xponent.mixco"}],2:[function(require,module,exports){
(function (process){
// mixco
// =====

if (process.env.MIXCO_USE_SOURCE) {
    require('coffee-script/register')
    module.exports = {
        behaviour: require('./src/behaviour'),
        control: require('./src/control'),
        script: require('./src/script'),
        transform: require('./src/transform'),
        util: require('./src/util'),
        value: require('./src/value')
    }
} else {
    module.exports = {
        behaviour: require('./lib/behaviour'),
        control: require('./lib/control'),
        script: require('./lib/script'),
        transform: require('./lib/transform'),
        util: require('./lib/util'),
        value: require('./lib/value')
    }
}

}).call(this,require('_process'))
},{"./lib/behaviour":3,"./lib/control":5,"./lib/script":6,"./lib/transform":7,"./lib/util":8,"./lib/value":9,"./src/behaviour":17,"./src/control":19,"./src/script":20,"./src/transform":21,"./src/util":22,"./src/value":23,"_process":12,"coffee-script/register":undefined}],3:[function(require,module,exports){
// Generated by CoffeeScript 1.10.0
(function() {
  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;
      }
    });
  };

}).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)) + "<status>" + (hexStr(this.status())) + "</status>\n" + (indent(depth)) + "<midino>" + (hexStr(this.midino)) + "</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)) + "<control>\n" + (indent(depth + 1)) + "<group>" + mapping.group + "</group>\n" + (indent(depth + 1)) + "<key>" + mapping.key + "</key>\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "<options>\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "</options>\n" + (indent(depth)) + "</control>";
    };

    InControl.prototype.configOptions = function(depth) {
      var opt, ref2;
      if (this.needsHandler()) {
        return (indent(depth)) + "<script-binding/>";
      } 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)) + "<normal/>";
      }
    };

    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)) + "<output>\n" + (indent(depth + 1)) + "<group>" + mapping.group + "</group>\n" + (indent(depth + 1)) + "<key>" + mapping.key + "</key>\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "<on>" + (hexStr(this._states['on'])) + "</on>\n" + (indent(depth + 1)) + "<off>" + (hexStr(this._states['off'])) + "</off>\n" + options + "\n" + (indent(depth)) + "</output>";
      }
    };

    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 <raskolnikov@gnu.org>",
      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 "<?xml version='1.0' encoding='utf-8'?>\n<MixxxControllerPreset mixxxVersion=\"1.11.0+\" schemaVersion=\"1\">\n" + (indent(1)) + "<info>\n" + (indent(2)) + "<name>" + (xmlEscape(this.info.name)) + "</name>\n" + (indent(2)) + "<author>" + (xmlEscape(this.info.author)) + "</author>\n" + (indent(2)) + "<description>" + (xmlEscape(this.info.description)) + "</description>\n" + (indent(2)) + "<wiki>" + (xmlEscape(this.info.wiki)) + "</wiki>\n" + (indent(2)) + "<forums>" + (xmlEscape(this.info.forums)) + "</forums>\n" + (indent(1)) + "</info>\n" + (indent(1)) + "<controller id=\"" + this.name + "\">\n" + (indent(2)) + "<scriptfiles>\n" + (indent(3)) + "<file functionprefix=\"" + this.name + "\"\n" + (indent(3)) + "      filename=\"" + this.name + ".mixco.output.js\"/>\n" + (indent(2)) + "</scriptfiles>\n" + (indent(2)) + "<controls>\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "</controls>\n" + (indent(2)) + "<outputs>\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "</outputs>\n" + (indent(1)) + "</controller>\n</MixxxControllerPreset>";
    };

    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('&', '&amp;').replace('"', '&quot;').replace('>', '&gt;').replace('<', '&lt;') : 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 environments 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 somebody has screwed with setTimeout but no I.E. madness
        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', hopefully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
        }
    }


}
function runClearTimeout(marker) {
    if (cachedClearTimeout === clearTimeout) {
        //normal environments 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 somebody has screwed with setTimeout but no I.E. madness
        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', hopefully 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 predictable 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 <jprichardson@gmail.com>
*/

!(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","ǲ":"D","ǅ":"D","Đ":"D","Ƌ":"D","Ǳ":"DZ","Ǆ":"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","ǈ":"L","Ł":"L","Ǉ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","ǋ":"N","Ñ":"N","Ǌ":"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","Œ":"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","é":"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","ſ":"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","ó":"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","ﬃ":"ffi","ﬄ":"ffl","ﬁ":"fi","ﬂ":"fl","ĳ":"ij","œ":"oe","ﬆ":"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<n; i++) {
        ss = ss.split(arguments[i]).join('');
      }
      return new this.constructor(ss);
    },

    stripLeft: function (chars) {
      var regex;
      var pattern;
      var ss = ensureString(this.s);

      if (chars === undefined) {
        pattern = /^\s+/g;
      }
      else {
        regex = escapeRegExp(chars);
        pattern = new RegExp("^[" + regex + "]+", "g");
      }

      return new this.constructor(ss.replace(pattern, ""));
    },

    stripRight: function (chars) {
      var regex;
      var pattern;
      var ss = ensureString(this.s);

      if (chars === undefined) {
        pattern = /\s+$/g;
      }
      else {
        regex = escapeRegExp(chars);
        pattern = new RegExp("[" + regex + "]+$", "g");
      }

      return new this.constructor(ss.replace(pattern, ""));
    },

    right: function(N) {
      if (N >= 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 = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };
  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 <raskolnikov@gnu.org>',
    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)) + "<status>" + (hexStr(this.status())) + "</status>\n" + (indent(depth)) + "<midino>" + (hexStr(this.midino)) + "</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)) + "<control>\n" + (indent(depth + 1)) + "<group>" + mapping.group + "</group>\n" + (indent(depth + 1)) + "<key>" + mapping.key + "</key>\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "<options>\n" + (this.configOptions(depth + 2)) + "\n" + (indent(depth + 1)) + "</options>\n" + (indent(depth)) + "</control>";
  };

  InControl.prototype.configOptions = function(depth) {
    var opt, ref2;
    if (this.needsHandler()) {
      return (indent(depth)) + "<script-binding/>";
    } 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)) + "<normal/>";
    }
  };

  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)) + "<output>\n" + (indent(depth + 1)) + "<group>" + mapping.group + "</group>\n" + (indent(depth + 1)) + "<key>" + mapping.key + "</key>\n" + (id.configMidi(depth + 1)) + "\n" + (indent(depth + 1)) + "<on>" + (hexStr(this._states['on'])) + "</on>\n" + (indent(depth + 1)) + "<off>" + (hexStr(this._states['off'])) + "</off>\n" + options + "\n" + (indent(depth)) + "</output>";
    }
  };

  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 <raskolnikov@gnu.org>",
    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 "<?xml version='1.0' encoding='utf-8'?>\n<MixxxControllerPreset mixxxVersion=\"1.11.0+\" schemaVersion=\"1\">\n" + (indent(1)) + "<info>\n" + (indent(2)) + "<name>" + (xmlEscape(this.info.name)) + "</name>\n" + (indent(2)) + "<author>" + (xmlEscape(this.info.author)) + "</author>\n" + (indent(2)) + "<description>" + (xmlEscape(this.info.description)) + "</description>\n" + (indent(2)) + "<wiki>" + (xmlEscape(this.info.wiki)) + "</wiki>\n" + (indent(2)) + "<forums>" + (xmlEscape(this.info.forums)) + "</forums>\n" + (indent(1)) + "</info>\n" + (indent(1)) + "<controller id=\"" + this.name + "\">\n" + (indent(2)) + "<scriptfiles>\n" + (indent(3)) + "<file functionprefix=\"" + this.name + "\"\n" + (indent(3)) + "      filename=\"" + this.name + ".mixco.output.js\"/>\n" + (indent(2)) + "</scriptfiles>\n" + (indent(2)) + "<controls>\n" + (this.configInputs(3)) + "\n" + (indent(2)) + "</controls>\n" + (indent(2)) + "<outputs>\n" + (this.configOutputs(3)) + "\n" + (indent(2)) + "</outputs>\n" + (indent(1)) + "</controller>\n</MixxxControllerPreset>";
  };

  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('&', '&amp;').replace('"', '&quot;').replace('>', '&gt;').replace('<', '&lt;') : 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 */