From 261f164d24548c60493186036bf39f21d51c9695 Mon Sep 17 00:00:00 2001 From: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> Date: Wed, 10 Nov 2021 19:09:04 +0100 Subject: [PATCH] Controllers: Add Mapping for Reloop Ready Initial commit of a mapping for the Reloop Ready controller. The Padmodes are not implemented and just default to the hotcues right now. The mapping currently depends on #4474 and #4495 --- res/controllers/Reloop Ready.midi.xml | 1602 +++++++++++++++++++++++ res/controllers/Reloop-Ready-scripts.js | 603 +++++++++ 2 files changed, 2205 insertions(+) create mode 100644 res/controllers/Reloop Ready.midi.xml create mode 100644 res/controllers/Reloop-Ready-scripts.js diff --git a/res/controllers/Reloop Ready.midi.xml b/res/controllers/Reloop Ready.midi.xml new file mode 100644 index 000000000000..7a0e928dc32f --- /dev/null +++ b/res/controllers/Reloop Ready.midi.xml @@ -0,0 +1,1602 @@ + + + + Reloop Ready + Swiftb0y + Almost feature-complete mapping of the Reloop Ready hardware. Development kindly sponsored by Samgarr + + + + + + + + + + + + + + + ReloopReady.components.leftDeck.jog.inputTouch + 0x90 + 0x06 + + + + + + ReloopReady.components.leftDeck.jog.inputTouch + 0x80 + 0x06 + + + + + + + ReloopReady.components.leftDeck.jog.inputWheel + 0xB0 + 0x06 + + + + + + + + ReloopReady.components.leftDeck.jog.inputTouch + 0x90 + 0x06 + + + + + + ReloopReady.components.leftDeck.jog.inputTouch + 0x81 + 0x06 + + + + + + + ReloopReady.components.leftDeck.jog.inputWheel + 0xB1 + 0x06 + + + + + + + + + ReloopReady.components.leftChannel.knob1.input + 0xB0 + 0x16 + + + + + + + ReloopReady.components.leftChannel.knob2.input + 0xB0 + 0x17 + + + + + + + ReloopReady.components.leftChannel.knob3.input + 0xB0 + 0x19 + + + + + + + ReloopReady.components.leftChannel.filter.input + 0xB0 + 0x1A + + + + + + + ReloopReady.components.leftChannel.volume.input + 0xB0 + 0x1C + + + + + + + ReloopReady.components.leftChannel.rate.inputMSB + 0xB0 + 0x09 + + + + + + + ReloopReady.components.leftChannel.rate.inputLSB + 0xB0 + 0x3F + + + + + + + + ReloopReady.components.leftChannel.load.input + 0x9E + 0x02 + + + + + + + ReloopReady.components.leftChannel.load.input + 0x8E + 0x02 + + + + + + + + ReloopReady.components.leftChannel.pfl.input + 0x90 + 0x1B + + + + + + + ReloopReady.components.leftChannel.pfl.input + 0x80 + 0x1B + + + + + + + + + ReloopReady.components.rightChannel.knob1.input + 0xB1 + 0x16 + + + + + + + ReloopReady.components.rightChannel.knob2.input + 0xB1 + 0x17 + + + + + + + ReloopReady.components.rightChannel.knob3.input + 0xB1 + 0x19 + + + + + + + ReloopReady.components.rightChannel.filter.input + 0xB1 + 0x1A + + + + + + + ReloopReady.components.rightChannel.volume.input + 0xB1 + 0x1C + + + + + + + ReloopReady.components.rightChannel.rate.inputMSB + 0xB1 + 0x09 + + + + + + + ReloopReady.components.rightChannel.rate.inputLSB + 0xB1 + 0x3F + + + + + + + + ReloopReady.components.rightChannel.load.input + 0x9E + 0x03 + + + + + + + ReloopReady.components.rightChannel.load.input + 0x8E + 0x03 + + + + + + + ReloopReady.components.rightChannel.load.input + 0x9E + 0x03 + + + + + + + ReloopReady.components.rightChannel.load.input + 0x8E + 0x03 + + + + + + + + ReloopReady.components.rightChannel.pfl.input + 0x91 + 0x1B + + + + + + + ReloopReady.components.rightChannel.pfl.input + 0x81 + 0x1B + + + + + + + + ReloopReady.components.leftChannel.fxUnit.level.input + 0xB8 + 0x00 + + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[0].input + 0x98 + 0x00 + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[0].input + 0x88 + 0x00 + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[1].input + 0x98 + 0x01 + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[1].input + 0x88 + 0x01 + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[2].input + 0x98 + 0x02 + + + + + + + ReloopReady.components.leftDeck.fxUnit.fxButtons[2].input + 0x88 + 0x02 + + + + + + + ReloopReady.components.leftDeck.fxUnit.loop.knob.input + 0xB4 + 0x34 + + + + + + + ReloopReady.components.leftDeck.fxUnit.loop.button.input + 0x94 + 0x40 + + + + + + + ReloopReady.components.leftDeck.fxUnit.loop.button.input + 0x84 + 0x40 + + + + + + + + + + ReloopReady.components.leftDeck.fxUnit.level.input + 0xB8 + 0x00 + + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[0].input + 0x99 + 0x00 + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[0].input + 0x89 + 0x00 + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[1].input + 0x99 + 0x01 + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[1].input + 0x89 + 0x01 + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[2].input + 0x99 + 0x02 + + + + + + + ReloopReady.components.rightDeck.fxUnit.fxButtons[2].input + 0x89 + 0x02 + + + + + + + ReloopReady.components.rightDeck.fxUnit.loop.knob.input + 0xB5 + 0x34 + + + + + + + ReloopReady.components.rightDeck.fxUnit.loop.button.input + 0x95 + 0x40 + + + + + + + ReloopReady.components.rightDeck.fxUnit.loop.button.input + 0x85 + 0x40 + + + + + + + + + ReloopReady.components.leftDeck.play.input + 0x90 + 0x00 + + + + + + + ReloopReady.components.leftDeck.play.input + 0x80 + 0x00 + + + + + + + ReloopReady.components.leftDeck.play.input + 0x90 + 0x10 + + + + + + + ReloopReady.components.leftDeck.play.input + 0x80 + 0x10 + + + + + + + + ReloopReady.components.rightDeck.play.input + 0x91 + 0x00 + + + + + + + ReloopReady.components.rightDeck.play.input + 0x81 + 0x00 + + + + + + + ReloopReady.components.rightDeck.play.input + 0x91 + 0x10 + + + + + + + ReloopReady.components.rightDeck.play.input + 0x81 + 0x10 + + + + + + + + + + + ReloopReady.components.leftDeck.cue.input + 0x90 + 0x01 + + + + + + + ReloopReady.components.leftDeck.cue.input + 0x80 + 0x01 + + + + + + + ReloopReady.components.leftDeck.cue.input + 0x90 + 0x05 + + + + + + + ReloopReady.components.leftDeck.cue.input + 0x80 + 0x05 + + + + + + + + ReloopReady.components.rightDeck.cue.input + 0x91 + 0x01 + + + + + + + ReloopReady.components.rightDeck.cue.input + 0x81 + 0x01 + + + + + + + ReloopReady.components.rightDeck.cue.input + 0x91 + 0x05 + + + + + + + ReloopReady.components.rightDeck.cue.input + 0x81 + 0x05 + + + + + + + + + + + + ReloopReady.components.leftDeck.sync.input + 0x90 + 0x02 + + + + + + + ReloopReady.components.leftDeck.sync.input + 0x80 + 0x02 + + + + + + + ReloopReady.components.leftDeck.sync.input + 0x90 + 0x03 + + + + + + + ReloopReady.components.leftDeck.sync.input + 0x80 + 0x03 + + + + + + + + ReloopReady.components.rightDeck.sync.input + 0x91 + 0x02 + + + + + + + ReloopReady.components.rightDeck.sync.input + 0x81 + 0x02 + + + + + + + ReloopReady.components.rightDeck.sync.input + 0x91 + 0x03 + + + + + + + ReloopReady.components.rightDeck.sync.input + 0x81 + 0x03 + + + + + + + + + ReloopReady.components.leftDeck.vinyl.input + 0x90 + 0x0F + + + + + + + ReloopReady.components.leftDeck.vinyl.input + 0x80 + 0x0F + + + + + + + ReloopReady.components.leftDeck.vinyl.input + 0x90 + 0x07 + + + + + + + ReloopReady.components.leftDeck.vinyl.input + 0x80 + 0x07 + + + + + + + + ReloopReady.components.rightDeck.vinyl.input + 0x91 + 0x0F + + + + + + + ReloopReady.components.rightDeck.vinyl.input + 0x81 + 0x0F + + + + + + + ReloopReady.components.rightDeck.vinyl.input + 0x91 + 0x07 + + + + + + + ReloopReady.components.rightDeck.vinyl.input + 0x81 + 0x07 + + + + + + + + + ReloopReady.components.leftDeck.keylock.input + 0x90 + 0x0D + + + + + + + ReloopReady.components.leftDeck.keylock.input + 0x80 + 0x0D + + + + + + + ReloopReady.components.leftDeck.keylock.input + 0x90 + 0x29 + + + + + + + ReloopReady.components.leftDeck.keylock.input + 0x80 + 0x29 + + + + + + + + ReloopReady.components.rightDeck.keylock.input + 0x91 + 0x0D + + + + + + + ReloopReady.components.rightDeck.keylock.input + 0x81 + 0x0D + + + + + + + ReloopReady.components.rightDeck.keylock.input + 0x91 + 0x29 + + + + + + + ReloopReady.components.rightDeck.keylock.input + 0x81 + 0x29 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[0].input + 0x94 + 0x14 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[0].input + 0x84 + 0x14 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[1].input + 0x94 + 0x15 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[1].input + 0x84 + 0x15 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[2].input + 0x94 + 0x16 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[2].input + 0x84 + 0x16 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[3].input + 0x94 + 0x17 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[3].input + 0x84 + 0x17 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[4].input + 0x94 + 0x18 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[4].input + 0x84 + 0x18 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[5].input + 0x94 + 0x19 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[5].input + 0x84 + 0x19 + + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[6].input + 0x94 + 0x1A + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[6].input + 0x84 + 0x1A + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[7].input + 0x94 + 0x1B + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[7].input + 0x84 + 0x1B + + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[0].input + 0x94 + 0x1C + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[0].input + 0x84 + 0x1C + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[1].input + 0x94 + 0x1D + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[1].input + 0x84 + 0x1D + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[2].input + 0x94 + 0x1E + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[2].input + 0x84 + 0x1E + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[3].input + 0x94 + 0x1F + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[3].input + 0x84 + 0x1F + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[4].input + 0x94 + 0x20 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[4].input + 0x84 + 0x20 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[5].input + 0x94 + 0x21 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[5].input + 0x84 + 0x21 + + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[6].input + 0x94 + 0x22 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[6].input + 0x84 + 0x22 + + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[7].input + 0x94 + 0x23 + + + + + + + ReloopReady.components.leftDeck.padUnit.pads[7].input + 0x84 + 0x23 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[0].input + 0x95 + 0x14 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[0].input + 0x85 + 0x14 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[1].input + 0x95 + 0x15 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[1].input + 0x85 + 0x15 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[2].input + 0x95 + 0x16 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[2].input + 0x85 + 0x16 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[3].input + 0x95 + 0x17 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[3].input + 0x85 + 0x17 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[4].input + 0x95 + 0x18 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[4].input + 0x85 + 0x18 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[5].input + 0x95 + 0x19 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[5].input + 0x85 + 0x19 + + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[6].input + 0x95 + 0x1A + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[6].input + 0x85 + 0x1A + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[7].input + 0x95 + 0x1B + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[7].input + 0x85 + 0x1B + + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[0].input + 0x95 + 0x1C + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[0].input + 0x85 + 0x1C + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[1].input + 0x95 + 0x1D + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[1].input + 0x85 + 0x1D + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[2].input + 0x95 + 0x1E + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[2].input + 0x85 + 0x1E + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[3].input + 0x95 + 0x1F + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[3].input + 0x85 + 0x1F + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[4].input + 0x95 + 0x20 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[4].input + 0x85 + 0x20 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[5].input + 0x95 + 0x21 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[5].input + 0x85 + 0x21 + + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[6].input + 0x95 + 0x22 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[6].input + 0x85 + 0x22 + + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[7].input + 0x95 + 0x23 + + + + + + + ReloopReady.components.rightDeck.padUnit.pads[7].input + 0x85 + 0x23 + + + + + + + + + ReloopReady.shift.input + 0x9E + 0x00 + + + + + + + ReloopReady.shift.input + 0x8E + 0x00 + + + + + + + + ReloopReady.components.crossfader.input + 0xBE + 0x08 + + + + + + + + ReloopReady.components.cueVol.input + 0xBE + 0x0C + + + + + + + ReloopReady.components.cueMix.input + 0xBE + 0x0D + + + + + + + ReloopReady.components.masterVol.input + 0xBE + 0x0A + + + + + + + + ReloopReady.components.browse.button.input + 0x9E + 0x06 + + + + + + + ReloopReady.components.browse.button.input + 0x8E + 0x06 + + + + + + + ReloopReady.components.browse.button.input + 0x9E + 0x7B + + + + + + + ReloopReady.components.browse.button.input + 0x8E + 0x7B + + + + + + + + ReloopReady.components.browse.knob.input + 0xBE + 0x00 + + + + + + + ReloopReady.components.browse.knob.input + 0xBE + 0x78 + + + + + + + + + + + + + + + + + diff --git a/res/controllers/Reloop-Ready-scripts.js b/res/controllers/Reloop-Ready-scripts.js new file mode 100644 index 000000000000..c4cb2e0a4908 --- /dev/null +++ b/res/controllers/Reloop-Ready-scripts.js @@ -0,0 +1,603 @@ +var ReloopReady = {}; + +/// The controller only offers Low, High and Gain Knobs, +/// settings this to true will remap them to control Low, Mid, High instead. +ReloopReady.threeBandEQ = false; + +ReloopReady.backlightButtons = true; + +/// scratch parameter, change to your liking +ReloopReady.scratchParams = { + alpha: 1/8, + beta: (1/8)/32, +}; + +/* +COLOR Notes: +{0: 'off', + 1: 'dim blue/purple', + 2: 'less dim blue/purple', + 3: 'even lesser dim blue/purple', + 4: 'dim green', + 5: 'dim turqiuose', + 6: 'less dim turquiose', + 7: 'even leeser dim turgiose', + 8: 'green', + 9: 'different dim turquoise', + 10: 'light blue/turqouse', + 11: 'light blue', + 12: 'different green', + 13: 'dim green/turqouse', + 14: 'dim blue/turqouse', + 15: 'dim blue/turqouse', + 16: 'very dim red', + 17: 'very dim purple', + 18: 'less dim purple', + 19: 'even lesser dim purple', + 20: 'dim yellow/green', + 21: 'dim white', + 22: 'dim white/blue', + 23: 'less dim white/blue', + 24: 'less dim green', + 25: 'light dim green/turqoise', + 26: 'light dim green/turqoise', + 27: 'light dim blue', + 28: 'green', + 29: 'light dim/turqoise', + 30: 'light dim gree turqoise', + 31: 'light deem blue turqoise', + 32: 'less dim red', + 33: 'less dim purple', + 34: 'less dim purple', + 35: 'less dim light purple', + 36: 'less dim yellow', + 37: 'less dim white', + 38: 'less dim white', + 39: 'less dim white/blue', + 40: 'less dim green', + 41: 'less dim blue turqoise', + 42: 'less dim frost', + 43: 'white/blue', + 44: 'green', + 45: 'repeating', + 46: '', + 47: '', + 48: 'dim red', + 49: 'repeating', + 50: '', + 51: '', + 52: '', + 53: '', + 54: '', + 55: '', + 56: '', + 57: '', + 58: '', + 59: '', + 60: '', + 61: '', + 62: '', + 63: '', + 64: 'off', + 65: 'blue', + 66: 'blue', + 67: 'bright blue', + 68: 'bright green', + 69: 'bright turqoise', + 70: 'bright green', + 71: 'bright blue', + 72: 'bright green', + 73: 'bright turqoise', + 74: 'same as dim pallet, just max brightness', + 75: '', + 76: '', + 77: '', + 78: '', + 79: '', + 80: '', + 81: '', + 82: '', + 83: '', + 84: '', + 85: '', + 86: '', + 87: '', + 88: '', + 89: '', + 90: '', + 91: '', + 92: '', + 93: '', + 94: '', + 95: '', + 96: '', + 97: '', + 98: '', + 99: '', + 100: '', + 101: '', + 102: '', + 103: '', + 104: '', + 105: '', + 106: '', + 107: '', + 108: '', + 109: '', + 110: '', + 111: '', + 112: '', + 113: '', + 114: '', + 115: '', + 116: '', + 117: '', + 118: '', + 119: '', + 120: '', + 121: '', + 122: '', + 123: '', + 124: '', + 125: '', + 126: '', + 127: ''} + + + +*/ + + +/** + * Misc. midi notes + * + * Note 0x31 firmware fader-start feature. Note 0x7F if volume fader is non-zero + */ + + +/** + * Color: + * The Reloop ready uses the entire 7-bit midi range for color. + * It encodes it in a simple to understand (but inefficient in regards to + * colors perceived by us) scheme: + * It uses the lower 6-bit for RGB colors (each channel having the unbelievable + * resolution of 2-bit), while the 7th-bit is used to switch between two + * brightness/intensity modes (with the 7th-bit set, meaning high brightness). + * + * |7654321| + * +-------+ + * |IRRGGBB| + * Example: the fullest, brightest red would have I set and the red channel on + * maximum: 0b1110000 + * + * Using that knowledge, we can extrapolate a 24-bit color from any 7-bit color: + */ + +ReloopReady.midiToFullColor = function(color) { + // not particularly fast in JS because doing bitwise stuff in JS is slow + // compared to bear-metal + + var b = color & 3; // ES3 does not support binary literals + var g = color >> 2 & 3; + var r = color >> 4 & 3; + var i = color >> 5 & 1; + + // this needs tweaking + i = i << 7; + b = (b << 5) | i; + g = (g << 5) | i; + r = (r << 5) | i; + + return (r << 16) | (g << 8) | b; +}; + +ReloopReady.padColorPalette = { + Red: 0xFF0000, + Green: 0x00FF00, + Blue: 0x0000FF, + Yellow: 0xFFFF00, + Cyan: 0x007FFF, + Purple: 0xFF00FF, +}; + +// IIFE for not leaking private variables +(function() { + + var fullColorToMidiColorMap = _(_.range(0x00, 0x80)) + .keyBy() + .mapKeys(ReloopReady.midiToFullColor) + .value(); + + ReloopReady.padColorMapper = new ColorMapper(fullColorToMidiColorMap); + + // transform padColorPalette to low-res midi approximations: + + ReloopReady.padColorPalette = _.mapValues(ReloopReady.padColorPalette, ReloopReady.padColorMapper.getValueForNearestColor); + +})(); + +components.Button.prototype.sendShifted = true; +components.Button.prototype.shiftControl = true; +// shift control offset depends on concrete control + +components.Encoder.prototype.inValueScale = function(value) { + // default implementation for converting signed ints + return value < 0x40 ? value : value - 0x80; +}; + +ReloopReady.singleColorLED = { + off: 0x00, + dim: 0x01, + lit: 0x7F, // anything between 0x02 and 0x7F is fully lit +}; + +// make Buttons backlight be default based on user-setting +components.Button.prototype.off = ReloopReady.backlightButtons ? ReloopReady.singleColorLED.dim : ReloopReady.singleColorLED.off; +components.Button.prototype.on = ReloopReady.singleColorLED.lit; + +ReloopReady.init = function() { + + // for (var i = 0; i < Object.keys(ReloopReady.padColorPalette).length; i++) { + // midi.sendShortMsg(0x95, i + 0x14, ReloopReady.padColorPalette[Object.keys(ReloopReady.padColorPalette)[i]]); + // } + + this.components = new components.ComponentContainer({ + leftDeck: new ReloopReady.Deck(0), + rightDeck: new ReloopReady.Deck(1), + leftChannel: new ReloopReady.Channel(0), + rightChannel: new ReloopReady.Channel(1), + }); + + this.components.crossfader = new components.Pot({ + group: "[Master]", + inKey: "crossfader" + }); + + this.components.masterVol = new components.Pot({ + group: "[Master]", + inKey: "gain" + }); + + this.components.cueMix = new components.Pot({ + group: "[Master]", + inKey: "headMix" + }); + + this.components.cueVol = new components.Pot({ + group: "[Master]", + inKey: "headGain" + }); + + this.components.browse = new components.ComponentContainer({ + button: new components.Button({ + unshift: function() { + this.group = "[Library]"; + this.inKey = "GoToItem"; + this.type = components.Button.prototype.types.push; + }, + shift: function() { + this.group = "[Master]"; + this.inKey = "maximize_library"; + this.type = components.Button.prototype.types.toggle; + } + }), + knob: new components.Encoder({ + group: "[Library]", + unshift: function() { + this.inKey = "MoveVertical"; + }, + shift: function() { + this.inKey = "MoveFocus"; + } + }) + }); + + var shiftableComponents = this.components; + + this.shift = new components.Button({ + input: function(channel, control, value, status, _group) { + if (this.isPress(channel, control, value, status)) { + shiftableComponents.shift(); + } else { + shiftableComponents.unshift(); + } + }, + }); +}; + +ReloopReady.shutdown = function() { + this.components.shutdown(); +}; + + + +ReloopReady.Channel = function(index) { + var channel = index + 1; + var group = "[Channel" + channel + "]"; + var eqGroup = "[EqualizerRack1_[Channel" + channel + "]_Effect1]"; + + if (ReloopReady.threeBandEQ) { + this.knob1 = new components.Pot({ + group: eqGroup, + inKey: "parameter3" + }); + this.knob2 = new components.Pot({ + group: eqGroup, + inKey: "parameter2" + }); + } else { + this.knob1 = new components.Pot({ + inKey: "pregain" + }); + + this.knob2 = new components.Pot({ + group: eqGroup, + inKey: "parameter3" + }); + } + + this.knob3 = new components.Pot({ + group: eqGroup, + inKey: "parameter1" + }); + + + this.filter = new components.Pot({ + group: "[QuickEffectRack1_[Channel" + channel + "]]", + inKey: "super1" + }); + + this.rate = new components.Pot({ + inKey: "rate", + max: 1023, + }); + + this.volume = new components.Pot({ + inKey: "volume", + }); + + this.pfl = new components.Button({ + midi: [0x90 + index, 0x1B], + shiftOffset: -0xD, + key: "pfl", + type: components.Button.prototype.types.toggle, + // input: script.midiDebug, + }); + + this.load = new components.Button({ + midi: [0x9E, 0x02 + index], + shiftOffset: 0x0D, + key: "LoadSelectedTrack" + }); + + + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = group; + } + }); +}; + +ReloopReady.Channel.prototype = new components.ComponentContainer(); + +ReloopReady.FxUnit = function(index) { + + var midiOn = 0x98 + index; + var channel = index + 1; + + this.level = new components.Pot({ + group: "EffectRack1_EffectUnit" + channel, + inKey: "super1" + }); + + this.fxButtons = Array(3); + for (var i = 0; i < this.fxButtons.length; i++) { + this.fxButtons[i] = new components.Button({ + midi: [midiOn, i], + shiftOffset: 0xA, + type: components.Button.prototype.types.toggle, + group: "[EffectRack1_EffectUnit" + channel + "_Effect" + (i + 1) + "]", + unshift: function() { + this.inKey = "enabled"; + this.outKey = this.inKey; + // this.input = components.Button.prototype.input; + }, + shift: function() { + // this.input = function(channel, control, value, status, _group) { + // if (this.isPress(channel, control, value, status)) { + // script.toggleControl(this.group, "next_effect"); + // } + // } + this.inKey = "next_effect"; + this.outKey = "loaded"; + } + }); + } + + this.loop = { + knob: new components.Encoder({ + group: "[Channel" + channel + "]", + input: function(_channel, _control, value, _status, _group) { + engine.setValue(this.group, value > 0x40 ? "loop_halve" : "loop_double", 1); + } + }), + button: new components.Button({ + group: "[Channel" + channel + "]", + input: function(channel, control, value, status, _group) { + if (this.isPress(channel, control, value, status)) { + if (this.shifted) { + // non standard behavior + script.bpm.tapButton(index); + } else { + script.triggerControl(this.group, "beatloop_activate"); + } + } + }, + }) + }; + + +}; + +ReloopReady.PadMode = function(obj) { + components.ComponentContainer.call(this, obj); + // interpret this an interface definition + this.index = obj.index; + this.pads = Array(8); + this.parameter1left = function() {}; + this.parameter1right = function() {}; + this.parameter2left = function() {}; + this.parameter2right = function() {}; + +}; +ReloopReady.PadMode.prototype = Object.create(components.ComponentContainer.prototype); + +ReloopReady.HotcuePadMode = function(obj) { + ReloopReady.PadMode.call(this, obj); + + for (var i = 0; i < this.pads.length; i++) { + this.pads[i] = new components.HotcueButton({ + midi: [0x94 + this.index, 0x14 + i], + group: "[Channel" + (this.index + 1) + "]", + shiftOffset: 0x8, + off: 0x00, + number: i + 1, + colorMapper: ReloopReady.padColorMapper, + }); + } +}; + +ReloopReady.HotcuePadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + +ReloopReady.AutoLoopPadMode = function(obj) { + ReloopReady.PadMode.call(this, obj); + this.setLoopSizes = function() { + + }; + + this.pads[4] = new components.Button({ + key: "beatjump_backward" + }); + // pads[5,6] TODO manual unclear + this.pads[7] = new components.Button({ + key: "beatjump_forward" + }); +}; + +ReloopReady.ManualLoopPadMode = function(obj) { + ReloopReady.PadMode.call(this, obj); + + this.pads[0] = new components.Button({ + key: "loop_in" + }); + this.pads[1] = new components.Button({ + key: "loop_out" + }); + this.pads[2] = new components.Button({ + key: "reloop" + }); + this.pads[3] = new components.Button({ + key: "loop_in_goto" + }); + + // lower pads not applicable to mixxx + +}; + +ReloopReady.SamplerPadMode = function(obj) { + ReloopReady.PadMode.call(this, obj); + + // this.pads +}; + +ReloopReady.PadContainer = function(_index) { + this.mode = function(_channel, _control, _value, _status, _group) { + + }; +}; + +ReloopReady.Deck = function(index) { + + var channel = index + 1; + + components.Deck.call(this, channel); + + var thisDeck = this; + var midiOn = 0x90 + index; + + + this.play = new components.PlayButton({ + midi: [midiOn, 0x00], + shiftOffset: 0x10, + shift: function() { + // match behavior labelled on hardware + this.inKey = "reverseroll"; + // todo fix interaction with shift button + }, + }); + + // needs matching cuemode to be used + this.cue = new components.CueButton({ + midi: [midiOn, 0x01], + shiftOffset: 0x04, + }); + + this.sync = new components.SyncButton({ + midi: [midiOn, 0x02], + shiftOffset: 0x1, + }); // investigate whether custom behavior is required to match controller + + this.vinyl = new components.Button({ + midi: [midiOn, 0x0F], + shiftOffset: -0x08, + shift: function() { + this.inKey = "slip_enabled"; + this.outKey = this.inKey; + this.input = components.Button.prototype.input; + }, + unshift: function() { + this.input = function(channel, control, value, status, _group) { + if (this.isPress(channel, control, value, status)) { + thisDeck.jog.vinylMode = ! thisDeck.jog.vinylMode; + this.output(thisDeck.jog.vinylMode); + } + }; + } + }); + + this.jog = new components.JogWheel({ + alpha: 1/8, + deck: channel, + wheelResolution: 300, + }); + + + this.keylock = new components.Button({ + midi: [midiOn, 0x0D], + shiftOffset: 0x1C, + type: components.Button.prototype.types.toggle, + shift: function() { + this.inKey = "sync_key"; + this.outKey = this.inKey; + }, + unshift: function() { + this.inKey = "keylock"; + this.outKey = this.inKey; + } + }); + + this.fxUnit = new ReloopReady.FxUnit(index); + + this.padUnit = new ReloopReady.HotcuePadMode({index: index}); + + + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = this.currentDeck; + } + }); + + print("this.currentDeck: " + this.currentDeck); +}; + +ReloopReady.Deck.prototype = new components.Deck();