summaryrefslogtreecommitdiffstats
path: root/res/controllers/Reloop-Beatpad-scripts.js
diff options
context:
space:
mode:
Diffstat (limited to 'res/controllers/Reloop-Beatpad-scripts.js')
-rw-r--r--res/controllers/Reloop-Beatpad-scripts.js5496
1 files changed, 2748 insertions, 2748 deletions
diff --git a/res/controllers/Reloop-Beatpad-scripts.js b/res/controllers/Reloop-Beatpad-scripts.js
index afda76c0b6..ea35aab3c5 100644
--- a/res/controllers/Reloop-Beatpad-scripts.js
+++ b/res/controllers/Reloop-Beatpad-scripts.js
@@ -1,2748 +1,2748 @@
-/***********************************************************************
- * ============== User Options =================
- *******************
- * TrackEndWarning *
- *******************
- * By default, when you reach the end of the track, the jog wheel are flashing.
- * set this variable just below to "false" instead of "true"
- * in order to disable this behaviour by default.
- * This can be toggled from the controller also (see the Wiki)
- * (idea by be.ing, member of the Mixxx team)
- **************************/
-var TrackEndWarning = true;
-/****************
- * scriptpause *
- ****************
- * period (in ms) while the script will be paused when sending messages
- * to the controller in order to avoid too much data flow at once in the same time.
- * - default value : 5 ms
- * - To disable : 0;
- **************************/
-var scriptpause = 5;
-
-/****************************
- * Constants for scratching *
- ****************************
- * Beatpad jog wheel is 800 intervals per revolution.
- * but the value has to be multiplied by 2 because
- * the scratch takes into account the track_samples in background
- * which is multiplied by 2 when the track is stereo
- ***************************/
-var intervalsPerRev = 1600,
- rpm = 33 + 1 / 3, //Like a real vinyl !!! :)
- alpha = 1.0 / 8, //Adjust to suit.
- beta = alpha / 32; //Adjust to suit.
-
-/*****************************
- * Constants for Jog Bending *
- *****************************
- * benConst is the acceleration parameter
- ************************ ***/
-var bendConst = 1/4; // Adjust to suit.
-
-
-/************************ GPL v2 licence *****************************
- * Reloop Beatpad controller script
- * Author: Chloé AVRILLON (DJ Chloé)
- *
- * Key features
- * ------------
- * - Light and Jog wheel light handling
- *- shift+wheelturn in "Jog Scratch" mode do automatic cut of the fader while scratching
- * - press/double press/long press handling
- **********************************************************************
- * User References
- * ---------------
- * Wiki/manual : http://www.mixxx.org/wiki/doku.php/reloop_beatpad
- * support forum : http://www.mixxx.org/forums/viewtopic.php?f=7&t=7581
- * e-mail : chloe.avrillon@gmail.com
- *
- * Thanks
- * ----------------
- * Thanks to authors of other scripts and particularly to authors of
- * Numark Dj2Go, KANE QuNeo, Vestax-VCI-400
- *
- * Revision history
- * ----------------
- * 2015-10-22 - Initial revision for Mixxx 1.12.0
- * 2015-10-22 - GPL v2 licence, rework of this header, JSHint.com quality check,
- * a few comments, minor changes, typos
- * 2015-11-24 - Make some code reusable (lights : LED object; Special Buttons, iCUT)
- * - pfl hidden bug fixed
- * - removed line duplicate in JumpBtn : deck.controls.jump.onOff(true);
- * (Mixxx bug was fixed : https://bugs.launchpad.net/mixxx/+bug/1504503)
- * - More comment in code
- * - Moved scratching constants with the global constants
- * - Fixed Jog Bending and fast search
- * - Sysex identification of the controller (nice print out in midiDebug).
- *
- * 2016-01-12 - Fixed FX effect selection on deck 2 (was selecting the entire chain instead (SHIFT+FX Select)
- * - Fixed SHIFT+PFL on the right deck
- * 2016-01-13 - removed a few unused variables, a useless return statement, corrected typos,
- * - modified "Jogger" object
- * --> Autocut feature (made it more "reusable")
- * --> model "A" and model "B" controller parameter
- * - move scratching and jog bending constant in user parameters section
- * - comments formatting
- *
- * This is a neverending story...
- ***********************************************************************
- * GPL v2 licence
- * --------------
- * Reloop Beatpad controller script script 1.3 for Mixxx 2.0+
- * Copyright (C) 2015-2016 Chloé AVRILLON
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-***********************************************************************/
-////////////////////////////////////////////////////////////////////////
-// JSHint configuration //
-////////////////////////////////////////////////////////////////////////
-/* global engine */
-/* global script */
-/* global print */
-/* global midi */
-////////////////////////////////////////////////////////////////////////
-
-function ReloopBeatpad() {}
-
-ReloopBeatpad(); // Very important ! Initializes rusable objects.
-
-// Array of Objects can be created
-ReloopBeatpad.decks = [];
-ReloopBeatpad.playlist = [];
-ReloopBeatpad.master = [];
-
-// Global constants/variables
-var ON = 0x7F,
- OFF = 0x00,
- DOWN = 0x7F,
- // UP = 0x00, // unused in the script, may be one day...
- SHIFT = -0x40,
- LBtn = 0x90,
- RBtn = 0x91,
- MBtn = 0x94,
- // Performance modes
- CUEMODE = 0,
- LOOPMODE = 1,
- FXMODE = 2,
- // 4 "Sampler" modes
- SAMPLERMODE = 3,
- SAMPLERBANKSTATUSMODE = 4,
- LOOPMODESTATUS = 5,
- FXRACKSELECTMODE = 6,
- // loop kind : simple normal loop mode/Loop roll mode
- SIMPLE = 1,
- ROLL = 2,
- HardwareLight = false,
- // Constant for special handling of some buttons
- QUICK_PRESS = 1, DOUBLE_PRESS = 2, LONG_PRESS = 3,
-
- // Sysex messages :
- // This Sysex message permits to ask the Reloop Beatpad for a complete
- // status of it's buttons, knobs and faders.
- // It is not used in the script anymore, Mixxx does it automatically.
- // just after the call to the init() function.
- // I leave it as a reference, commented.
- // ControllerStatusSysex = [0xF0, 0x26, 0x2D, 0x65, 0x22, 0xF7],
-
- // This Sysex message asks the controller (it's very generic and works
- // for a lot of MIDI controllers). Sending this to the controller will
- // be followed by a Sysex sent by the controllers giving some
- // values that permits to identify it (have a look far at the end
- // of this mapping script
- SysexIDRequest = [0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7];
-
-// Utilities
-//======================================================================
-function pauseScript(ms) {
- if (ms>0) {
- var startDate = new Date();
- var currentDate = null;
- while (currentDate - startDate < ms) {
- currentDate = new Date();
- }
- }
-}
-
-Math.sign = Math.sign || function(x) {
- x = +x; // convert the parameter into a number
- if (x === 0 || isNaN(x)) {
- return x;
- }
- return x > 0 ? 1 : -1;
-};
-
-function intpart(n) {
- if (n<0) {
- return Math.ceil(n);
- } else {
- return Math.floor(n);
- }
-}
-
-function toggleValue(group,key) {
- engine.setValue(group,key,!engine.getValue(group,key));
-}
-
-function IsStereo(group) {
- // this is an integer
- var d1 = engine.getValue(group, "duration");
- // this is a real value
- var d2 = engine.getValue(group, "track_samples") / engine.getValue(group, "track_samplerate");
- if (d1==d2) {
- return false;
- } else {
- if ( (d1 < Math.floor(d2)) && (d1 < Math.ceil(d2)) ) {
- return false;
- } else {
- return true;
- }
- }
-}
-
-function TrackIsLoaded(group) {
- return (engine.getValue(group, "track_samples") > 0) ? true : false;
-}
-
-function RealDuration(group) {
- var ts = engine.getValue(group, "track_samples");
- if (ts <= 0) {
- return 0;
- } else {
- // this is an integer :
- var d1 = engine.getValue(group, "duration");
- // this is a real value :
- var d2 = engine.getValue(group, "track_samples") / engine.getValue(group, "track_samplerate");
-
- if (d1==d2) {
- // it is mono
- return d2;
- } else {
- if ( (d1 > Math.floor(d2)) && (d1 < Math.ceil(d2)) ) {
- // It is mono
- return d2;
- } else {
- // It is stereo
- return d2/2;
- }
- }
- }
-}
-
-function TurnLEDsOff() {
- // Turn all LEDS off
- var i,j;
- for (i = LBtn; i <= RBtn; i++) { // 2 decks
- midi.sendShortMsg(i, 0x41, OFF);
- midi.sendShortMsg(i, 0x42, OFF);
- midi.sendShortMsg(i, 0x44, OFF);
- for (j = 0x47; j <= 0x62; j++) {
- midi.sendShortMsg(i, j, OFF);
- midi.sendShortMsg(i, j + SHIFT, OFF);
- }
- for (j = 0x66; j <= 0x6C; j++) {
- midi.sendShortMsg(i, j, OFF);
- }
- }
-}
-
-// Constants
-// ======================================================================
-ReloopBeatpad.MIDI = {
- rec: 0x41,
- Trackpush: 0x46,
- BendMinus: 0x41,
- BendPlus: 0x42,
- // Jog modes
- Vinyl: 0x45,
- iScratch: 0x46,
- // Pitch+FX switches
- Loop: 0x44,
- Loop_size_push: 0x43,
- FX_ON: 0x47,
- // Performance mode
- Cue: 0x48,
- Loop_Bounce: 0x49,
- InstantFX: 0x4A,
- Sampler: 0x4B,
- CuePad: 0x4C, // (4 Buttons 0x4C~0x4F (+0--+4)
- LoopPad: 0x50, // (4 Buttons 0x50~0x53 (+0--+4)
- FXPad: 0x54, // (4 Buttons 0x54~0x57 (+0--+4)
- SamplerPad: 0x58, // (4 Sampler Buttons 0x58~0x5B (+0--+4) (RGB color leds)
- Shift: 0x5C,
- mSync: 0x5D,
- Set: 0x5E, // "Cue Play" in the Beatpad documentation
- Jump: 0x5F, // "MainCue" in the Beatpad documentation
- Play: 0x60,
- pfl: 0x61,
- Load: 0x62,
- VUMeter: 0x66, // values : 0x00~0x08
- // Vinyl RIM Leds
- RIM_Red: 0x67, // 1st behaviour 0x01-0x18 ; 2nd Behavior = 1st +24 ;3d behavior ON/OFF
- RIM_Blue: 0x68, // 1st behaviour 0x05-0x08 ; 2nd Behavior = 1st -4;3d behavior ON/OFF
- RIM_RGB: 0x69 // 4 RGB Leds 0x69~0x6C (+0--+4) : for values, see ReloopBeatpad.RGB just below
-};
-
-// Colors used by the jogwheels
-ReloopBeatpad.RGB = {
- black: 0x00,
- red: 0x01,
- green: 0x02,
- blue: 0x03,
- yellow: 0x04,
- magenta: 0x05,
- cyan: 0x06,
- white: 0x07
-};
-
-// Colors used by the PADs (in Sampler mode)
-ReloopBeatpad.PadColor = {
- black: 0x00,
- blue: 0x01,
- magenta: 0x02,
- uv: 0x03,
- purple: 0x04,
- indigo: 0x05,
- fushia: 0x06,
- lilac: 0x07,
- orange: 0x08
-};
-
-// =====================================================================
-// Reusable Objects (special buttons handling, LEDs, iCUT and Jog wheels)
-// =====================================================================
-
-// LED class object
-var LED = function(control, midino) {
- this.control = control;
- this.midino = midino;
- this.lit = 0;
- this.flashTimer = 0;
- this.flashTimer2 = 0;
- this.flashOnceTimer = 0;
- this.flashDuration = 0;
- this.flashOnceDuration = 0;
-
- this.num_ms_on = 0;
- this.valueon = 0;
- this.num_ms_off = 0;
- this.flashCount = 0;
- this.relight = 0;
- this.valueoff = 0;
-};
-
-// public : light on/off
-LED.prototype.onOff = function(value) {
- // stop pending flashing effects now
- if (this.flashTimer !== 0) {
- engine.stopTimer(this.flashTimer);
- this.flashTimer = 0;
- this.flashDuration = 0;
- }
-
- if (this.flashTimer2 !== 0) {
- engine.stopTimer(this.flashTimer2);
- this.flashTimer2 = 0;
- this.flashDuration = 0;
- }
-
- if (this.flashOnceTimer !== 0) {
- engine.stopTimer(this.flashOnceTimer);
- this.flashOnceTimer = 0;
- this.flashOnceDuration = 0;
- }
- midi.sendShortMsg(this.control, this.midino, value);
- pauseScript(scriptpause);
- this.lit = value;
-};
-
-// public : make a light flashing
-//-------------------------------
-// num_ms_on : number of ms the light should stay enlighted when blinking
-// value : value to send to the controller to lit it up,
-// generally 0x00 means OFF, 0x7F means ON, but the light
-// can receive some other values if it can have various colors
-// num_ms_off : number of ms the light should be switched off when blinking
-// flashcount : number of time the light should blink (3 times ? 10 times ? only once (1) ?
-// if set to 0 or not set, flashes for ever, can be stopped with flashOff()
-// relight : once the light has finished to blink, should we restore it in its original state (true) or must it be switched off (false).
-// if not set, it considers it as a switch off (default=false)
-// valueoff : like "value". That permits for instance with two colors (once red(on), once blue(off), once red(on), etc...)
-LED.prototype.flashOn = function(num_ms_on, value, num_ms_off, flashCount, relight, valueoff) {
- var myself = this;
-
- // stop pending timers
- this.flashOff();
-
- // init
- this.flashDuration = num_ms_on;
- this.num_ms_on = num_ms_on;
- this.valueon = value;
- this.num_ms_off = num_ms_off;
- this.flashCount = flashCount;
- this.relight = relight;
- this.valueoff = valueoff;
-
- // 1st flash
- // This is because the permanent timer below takes
- // num_ms_on milisecs before first flash.
- this.flashOnceOn(num_ms_on, value);
-
- if (flashCount !== 1) {
- // flashcount =0 means permanent flash,
- // flashcount>0 , means temporary flash, first flash already done,
- // so we don't need this part if flashcount=1
- // permanent timer
-
- this.flashTimer = engine.beginTimer( num_ms_on + num_ms_off, function(){ myself.flashOnceOn(false); } );
- }
- if (flashCount > 1) {
- // flashcount>0 , means temporary flash, first flash already done,
- // so we don't need this part if flashcount=1
- // temporary timer. The end of this timer stops the permanent flashing
-
- this.flashTimer2 = engine.beginTimer(flashCount * (num_ms_on + num_ms_off) - num_ms_off, function(){ myself.Stopflash(relight); }, true);
- }
-};
-
-// public
-LED.prototype.getFlashDuration = function() {
- return this.flashDuration;
-};
-
-LED.prototype.checkOn = function() {
- return this.lit;
-};
-
-// private : relight=true : restore light state before it was flashing
-// this is a call back function (called in flashon() )
-LED.prototype.flashOff = function(relight) {
- // stop permanent timer if any
- if (this.flashTimer !== 0) {
- engine.stopTimer(this.flashTimer);
- // reset flash variables to 0
- this.flashTimer = 0;
- }
- if (this.flashTimer2 !== 0) {
- engine.stopTimer(this.flashTimer2);
- // reset flash variables to 0
- this.flashTimer2 = 0;
- }
- this.flashDuration = 0;
- if (relight) {
- this.onOff(this.lit);
- } else {
- this.onOff(OFF);
- }
-};
-
-// private : relight=true : restore light state before it was flashing
-// this is a call back function (called in flashon() )
-LED.prototype.Stopflash = function(relight) {
- // stop permanent timer
- if (this.flashTimer !== 0) {
- engine.stopTimer(this.flashTimer);
- }
- // reset flash variables to 0
- this.flashTimer = 0;
- this.flashTimer2 = 0;
- this.flashDuration = 0;
- this.flashOff(relight);
-};
-
-// private : call back function (called in flashon() )
-LED.prototype.flashOnceOn = function(relight) {
- var myself = this;
- midi.sendShortMsg(this.control, this.midino, this.valueon);
- pauseScript(scriptpause);
- this.flashOnceDuration = this.num_ms_on;
- this.flashOnceTimer = engine.beginTimer(this.num_ms_on - scriptpause, function(){ myself.flashOnceOff(relight); }, true);
-};
-
-// private :call back function (called in flashOnceOn() )
-LED.prototype.flashOnceOff = function(relight) {
- this.flashOnceTimer = 0;
- this.flashOnceDuration = 0;
-
- if (relight) {
- midi.sendShortMsg(this.control, this.midino, this.lit);
- pauseScript(scriptpause);
- } else {
- midi.sendShortMsg(this.control, this.midino, this.valueoff);
- pauseScript(scriptpause);
- this.lit = OFF;
- }
-};
-
-// ********* special buttons handlers (SHIFT ,LOAD and SYNC buttons)
-// ======================= SingleDoubleBtn
-// Callback : Callback function you have to provide (see end of
-// the code), that will return the original event
-// parameters (channel, control, value, status, group)
-// and the kind of press event affecting your button
-// (eventkind).
-// This callback will be triggered as soon as you
-// press the button a second time (Value will be
-// equal to DOWN), or the Long press is asserted
-// (value = DOWN because you are still holding down
-// the button or value=UP because you have released
-// the button only once before it becomes a long press).
-// DoublePressTimeOut : delay in ms above which a second press on the
-// button will not be considered as a potential double
-// but as a new press cycle event (default = 400ms).
-var SingleDoubleBtn = function(Callback, DoublePressTimeOut) {
- this.channel = 0;
- this.control = 0;
- this.value = 0;
- this.status = 0;
- this.group = "";
- this.Callback = Callback;
- if (DoublePressTimeOut) {
- this.DoublePressTimeOut = DoublePressTimeOut;
- } else {
- // Sets a default value of 400 ms
- this.DoublePressTimeOut = 400;
- }
- this.ButtonCount = 0;
- this.ButtonTimer = 0;
-};
-
-// Button pressed
-SingleDoubleBtn.prototype.ButtonDown = function(channel, control, value, status, group) {
- var myself = this;
- this.channel = channel;
- this.control = control;
- this.value = value;
- this.status = status;
- this.group = group;
- if (this.ButtonTimer === 0) { // first press
-
- this.ButtonTimer =
- engine.beginTimer(this.DoublePressTimeOut,
- function(){ myself.ButtonDecide(); }, true);
- this.ButtonCount = 1;
- } else { // 2nd press (before timer's out)
- engine.stopTimer(this.ButtonTimer);
- this.ButtonTimer = 0;
- this.ButtonCount = 2;
- this.ButtonDecide();
- }
-};
-
-// Take action
-SingleDoubleBtn.prototype.ButtonDecide = function() {
- this.ButtonTimer = 0;
- this.Callback(this.channel, this.control, this.value, this.status, this.group, this.ButtonCount);
- this.ButtonCount = 0;
-};
-
-// ======================= LongShortBtn
-// Callback : Callback function you have to provide (see end of the code), that will return
-// the original event parameters (channel, control, value, status, group)
-// and the kind of press event affecting your button (eventkind)
-// This callback will be called once you release the button
-// (Value will be equal to UP). You must provide this parameter.
-// LongPressThreshold : delay in ms above which a first press on the
-// button will be considered as a Long press (default = 500ms).
-// This parameter is optional.
-// CallBackOKLongPress : This callback will give you the same values than the first one
-// but it will be triggered as soon as the Long press is taken
-// into account ( at this moment, value = DOWN because you are still
-// holding down the button). This permits for instance to lit up a light indicating
-// the user that he/she can release the button. This callback occurs before the first one.
-// This parameter is optional.
-// Like that, you can decide to put the code for the long press in either callback function
-var LongShortBtn = function(Callback, LongPressThreshold, CallBackOKLongPress) {
- this.Callback = Callback;
- this.channel = 0;
- this.control = 0;
- this.value = 0;
- this.status = 0;
- this.group = "";
- this.CallBackOKLongPress = CallBackOKLongPress;
- if (LongPressThreshold) {
- this.LongPressThreshold = LongPressThreshold;
- } else {
- // Sets a default value of 500 ms
- this.LongPressThreshold = 500;
- }
-
- this.ButtonLongPress = false;
- this.ButtonLongPressTimer = 0;
-};
-
-// Timer's call back for long press
-LongShortBtn.prototype.ButtonAssertLongPress = function() {
- this.ButtonLongPress = true;
- // the timer was stopped, we set it to zero
- this.ButtonLongPressTimer = 0;
- // let's take action of the long press
- // Make sure the callback is a function​ and exist
- if (typeof callback === "function") {
- // Call it, since we have confirmed it is callable​
- this.CallBackOKLongPress(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS);
- }
-};
-
-LongShortBtn.prototype.ButtonDown = function(channel, control, value, status, group) {
- var myself = this;
- this.channel = channel;
- this.control = control;
- this.value = value;
- this.status = status;
- this.group = group;
- this.ButtonLongPress = false;
- this.ButtonLongPressTimer = engine.beginTimer(this.LongPressThreshold, function(){ myself.ButtonAssertLongPress(); }, true);
-};
-
-LongShortBtn.prototype.ButtonUp = function() {
- if (this.ButtonLongPressTimer !== 0) {
- engine.stopTimer(this.ButtonLongPressTimer);
- this.ButtonLongPressTimer = 0;
- }
- if (this.ButtonLongPress) {
- this.Callback(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS);
- } else {
- this.Callback(this.channel, this.control, this.value, this.status, this.group, QUICK_PRESS);
- }
-};
-
-// ======================= LongShortDoubleBtn
-// Callback : Callback function you have to provide (see end of
-// the code), that will return the original event
-// parameters (channel, control, value, status, group)
-// and the kind of press event affecting your button
-// (eventkind).
-// This callback will be triggered as soon as you
-// press the button a second time (Value will be
-// equal to DOWN), or the Long press is asserted
-// (value = DOWN because you are still holding down
-// the button or value=UP because you have released
-// the button only once before it becomes a long press).
-// LongPressThreshold : delay in ms above which a first press on the
-// button will be considered as a Long press (default = 500ms).
-// DoublePressTimeOut : delay in ms above which a second press on the
-// button will not be considered as a potential double
-// but as a new press cycle event (default = 400ms).
-var LongShortDoubleBtn = function(Callback, LongPressThreshold, DoublePressTimeOut) {
- this.Callback = Callback;
- this.channel = 0;
- this.control = 0;
- this.value = 0;
- this.status = 0;
- this.group = "";
- if (LongPressThreshold) {
- this.LongPressThreshold = LongPressThreshold;
- } else {
- // Sets a default value of 500 ms
- this.LongPressThreshold = 500;
- }
- if (DoublePressTimeOut) {
- this.DoublePressTimeOut = DoublePressTimeOut;
- } else {
- // Sets a default value of 400 ms
- this.DoublePressTimeOut = 400;
- }
- this.ButtonTimer = 0;
- this.ButtonLongPress = false;
- this.ButtonLongPressTimer = 0;
- this.ButtonCount = 0;
-};
-
-// Timer's call back for long press
-LongShortDoubleBtn.prototype.ButtonAssertLongPress = function() {
- this.ButtonLongPress = true;
- // the timer was stopped, we set it to zero
- this.ButtonLongPressTimer = 0;
- // let's take action of the long press
- this.ButtonDecide();
-};
-
-// Timer's callback for single press/double press
-LongShortDoubleBtn.prototype.ButtonAssert1Press = function() {
- // Short Timer ran out before it was manually stopped by release
- // of the button (ButtonUp):
- // for sure it is a single click (short or long), we will know
- // when button will be released or when longtimer will stop by itself
-
- // the timer was stopped, we set it to zero
- this.ButtonTimer = 0;
- this.ButtonCount = 1;
- if (this.ButtonLongPressTimer === 0) {
- // long press timer was stopped (short press)
- // take action
- this.ButtonDecide();
- }
-};
-
-// Button pressed (function called by mapper's code)
-LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, status, group) {
- var myself = this;
- this.channel = channel;
- this.control = control;
- this.value = value;
- this.status = status;
- this.group = group;
-
- if (this.ButtonCount === 0) { // first press (inits)
- // 1st press
- this.ButtonCount = 1;
- // and short press
- this.ButtonLongPress = false;
- this.ButtonLongPressTimer =
- engine.beginTimer(this.LongPressThreshold,
- function(){ myself.ButtonAssertLongPress(); },
- true);
- this.ButtonTimer =
- engine.beginTimer(this.DoublePressTimeOut,
- function(){ myself.ButtonAssert1Press(); },
- true);
- } else if (this.ButtonCount == 1) { // 2nd press (before short timer's out)
- // stop timers...
- if (this.ButtonLongPressTimer !== 0) {
- engine.stopTimer(this.ButtonLongPressTimer);
- this.ButtonLongPressTimer = 0;
- }
- // we stopped the timer, we have to set it to zero.
- // You must have this reflex : "stopTimer(timer)/timer=0" in mind
- // so that you can test later on if it is active or not. Other else
- // it's value stays with the one given by engine.beginTimer
-
- // "stopTimer(timer)/timer=0"
- if (this.ButtonTimer !== 0) {
- engine.stopTimer(this.ButtonTimer);
- this.ButtonTimer = 0 ;
- }
-
- // 2nd press
- this.ButtonCount = 2;
-
- // ...and take action immediately
- this.ButtonDecide();
- } // else :
- // 2nd press after short timer's out, this cannot happen,
- // do nothing
-};
-
-// Button released (function called by mapper's code)
-LongShortDoubleBtn.prototype.ButtonUp = function() {
- // button released
- if (this.ButtonLongPress === false) {
- // long press was not asserted by timer (ButtonAssertLongPress)
- // Button is released before timer's out
-
- // If first Buttun up, long timer is still running
- // stop long timer if it is still running, keep short timer,
- // longpress will never happen
- if (this.ButtonLongPressTimer !== 0) {
- engine.stopTimer(this.ButtonLongPressTimer);
- this.ButtonLongPressTimer = 0;
- }
- } //else :
- // longpressed is confirmed, we already took action in ButtonAssertLongPress
-};
-
-// Take actions and call callback
-LongShortDoubleBtn.prototype.ButtonDecide = function() {
- if (this.ButtonLongPressTimer !== 0) {
- engine.stopTimer(this.ButtonLongPressTimer);
- }
- this.ButtonLongPressTimer = 0;
- this.ButtonTimer = 0;
-
- if (this.ButtonLongPress) {
- this.Callback(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS);
- } else {
- if (this.ButtonCount == 2) {
- this.Callback(this.channel, this.control, this.value, this.status, this.group, DOUBLE_PRESS);
- } else { // We pressed sync only once
- this.Callback(this.channel, this.control, this.value, this.status, this.group, QUICK_PRESS);
- }
- }
- // re-init
- this.ButtonCount = 0;
- this.ButtonLongPress = false;
-};
-
-
-// *************************************************
-// iCut mode management
-// ****
-// According to the Quick start guide :
-// iCut MODE :
-// DJAY will automatically cut your track with the
-// cross fader when holding SHIFT and scratching
-// with the jog wheel
-// According to Reloop Website : http://www.reloop.com/reloop-beatpad (Explorer tab)
-// iCut :
-// "this mode simulates a scratch routine. When the jog wheel is turned back
-// the crossfader closes, when the jog wheel is turned forward the crossfader
-// will open."
-// In Practice : DJAY software is closing/opening the crossfader
-// quickly without taking into account the direction of the wheel.
-// Here I am trying to stick with the reloop explanation :
-// it is the "as it is supposed to be done"
-var AutoCut = function (deckNum) {
- this.deckNum = deckNum;
- this.timer = 0;
- this.delay = 20;
- this.fadersave = 0;
- this.enabled = false;
-};
-
-AutoCut.prototype.On = function() {
- if (!this.enabled) {
- this.enabled = true;
- engine.softTakeover("[Master]", "crossfader", false);
- }
-};
-
-AutoCut.prototype.FaderCut = function(jogValue) {
- if (this.enabled) {
- var direction = Math.sign(jogValue); //Get Jog wheel direction
- // Backward=-1 (close), forward =0 (open)
- if (direction > 0) {
- direction = 0;
- }
- // Left Deck ? direction = 0 (open : crossfader to zéro) or 1 (close : crossfader to the right)
- // Right Deck ? direction = 0 (open : crossfader to zéro) or -1 (close : crossfader to the left)
- if (this.deckNum == 1) {
- direction = -direction;
- } // else direction is of the good sign
- engine.setValue('[Master]', 'crossfader', direction);
- }
-};
-
-AutoCut.prototype.Off = function() {
- if (this.enabled) {
- this.enabled = false;
- engine.setValue('[Master]', 'crossfader', 0);
- engine.softTakeover("[Master]", "crossfader", true);
- }
-};
-
-// *****************************************************************
-// Jog wheel management (scratching, bending, ...)
-// ******
-// Thank you to the authors of the Vestax VCI 400 mapping script
-// model : model of your controller, should be "A" or "B".
-// Your controller is a "Model A" controller for scratching,
-// if it centers on 0.
-// Your controller is a "Model B" controller for scratching,
-// if it centers on 0x40 (64)
-// See http://www.mixxx.org/wiki/doku.php/midi_scripting#scratching
-var Jogger = function (group, deckNum, model) {
- this.deckNum = deckNum;
- this.group = group;
- this.wheelTouchInertiaTimer = 0;
- this.iCUT = new AutoCut(deckNum);
- this.model = model;
-};
-
-Jogger.prototype.finishWheelTouch = function() {
- var myself = this;
- this.wheelTouchInertiaTimer = 0;
- var play = engine.getValue(this.group, "play");
- if (play !== 0) {
- // If we are playing, just hand off to the engine.
- this.iCUT.Off();
- engine.scratchDisable(this.deckNum, true);
- } else {
- // If things are paused, there will be a non-smooth handoff
- // between scratching and jogging.
- // Instead, keep scratch on until the platter is not moving.
- var scratchRate = Math.abs(engine.getValue(this.group, "scratch2"));
- if (scratchRate < 0.01) {
- // The platter is basically stopped, now we can disable
- // scratch and hand off to jogging.
- this.iCUT.Off();
- engine.scratchDisable(this.deckNum, false);
- } else {
- // Check again soon.
- this.wheelTouchInertiaTimer =
- engine.beginTimer(100,
- function(){ myself.finishWheelTouch(); },
- true);
- }
- }
-};
-
-Jogger.prototype.onWheelTouch = function(value,Do_iCut) {
- var myself = this;
- if (Do_iCut) {
- this.iCUT.On();
- } else {
- this.iCUT.Off();
- }
-
- if (this.wheelTouchInertiaTimer !== 0) {
- // The wheel was touched again, reset the timer.
- engine.stopTimer(this.wheelTouchInertiaTimer);
- this.wheelTouchInertiaTimer = 0;
- }
-
- if (value == DOWN) {
- // Hand on the Jog wheel, scratch activated
- engine.scratchEnable(this.deckNum, intervalsPerRev, rpm, alpha, beta);
- } else {
- // The wheel touch sensor can be overly sensitive, so don't release scratch mode right away.
- // Depending on how fast the platter was moving, lengthen the time we'll wait.
- var scratchRate = Math.abs(engine.getValue(this.group, "scratch2"));
- var inertiaTime = Math.pow(1.8, scratchRate) * 50;
- if (inertiaTime < 100) {
- // Just do it now.
- this.finishWheelTouch();
- } else { // If button up
- this.wheelTouchInertiaTimer =
- engine.beginTimer(inertiaTime,
- function(){ myself.finishWheelTouch(); },
- true);
- }
- }
-};
-
-Jogger.prototype.onWheelMove = function(value, Do_iCut) {
- var jogValue;
- if (this.model=="A") {
- if (value-64 > 0) jogValue = value - 128;
- else jogValue = value;
- } else { // Model B controller
- jogValue = value - 0x40;
- }
-
- // Note that we always set the jog value even if scratching is active. This seems
- // to create a better handoff between scratching and not-scratching.
- if (engine.getValue(this.group, "play")) {
- engine.setValue(this.group, "jog", jogValue / (bendConst*10));
- } else {
- engine.setValue(this.group, "jog", jogValue / (bendConst*2.5));
- }
- if (engine.getValue(this.group, "scratch2_enable")) {
- // if "control"<0x40, then the DJ is doing a SHIFT+JogWheel (iCut with Dejay from Algorriddim)
- // if "Jog Scratch" mode is activated on the Beatpad, we have for the "control" value
- // Left JogWheel --> 0x63, +SHIFT --> 0x23
- // Right JogWheel --> 0x65, +SHIFT --> 0x25
- if (Do_iCut) {
- this.iCUT.On();
- } else {
- this.iCUT.Off();
- }
- this.iCUT.FaderCut(jogValue);
- // Register the movement :
- engine.scratchTick(this.deckNum, jogValue);
- }
-};
-
-// =====================================================================
-// Specific objects for the Reloop Beatpad
-// =====================================================================
-
-// ******************************************************************
-// RGB Jog Leds management
-// *********
-// Some explanation about this part which control the lights (colors, flashing effect, and so forth)
-// of the jog wheels. It is based on the generic LED object code above.
-// It is a layered structure like layers in paint programs.
-// The lowest level (0) is the background and the highest is the foreground (show 6)
-// Each of the layer permits to act like a mask for the lower ones.
-// Each show corresponds to a light show to indicate whether you apply an effect, the lp/hp filter , loops, etc
-// The jogwheel has 4 RGB leds , so there is 4 slots for each show.
-// let's that we have toggle an Effect of the effect rack (show 1), the jog wheel
-/