From 9518045c5f75494803c3dfac02f9858b451e2be7 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, #4495 and #4512 --- res/controllers/Reloop Ready.midi.xml | 1983 +++++++++++++++++++++++ res/controllers/Reloop-Ready-scripts.js | 875 ++++++++++ 2 files changed, 2858 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..5cd5bc745d4d --- /dev/null +++ b/res/controllers/Reloop Ready.midi.xml @@ -0,0 +1,1983 @@ + + + + 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.rightDeck.jog.inputTouch + 0x91 + 0x06 + + + + + + ReloopReady.components.rightDeck.jog.inputTouch + 0x81 + 0x06 + + + + + + + ReloopReady.components.rightDeck.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.pfl.input + 0x91 + 0x1B + + + + + + + ReloopReady.components.rightChannel.pfl.input + 0x81 + 0x1B + + + + + + + + ReloopReady.components.leftDeck.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.currentLayer.pads[0].input + 0x94 + 0x14 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[0].input + 0x84 + 0x14 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[1].input + 0x94 + 0x15 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[1].input + 0x84 + 0x15 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[2].input + 0x94 + 0x16 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[2].input + 0x84 + 0x16 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[3].input + 0x94 + 0x17 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[3].input + 0x84 + 0x17 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[4].input + 0x94 + 0x18 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[4].input + 0x84 + 0x18 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[5].input + 0x94 + 0x19 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[5].input + 0x84 + 0x19 + + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[6].input + 0x94 + 0x1A + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[6].input + 0x84 + 0x1A + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[7].input + 0x94 + 0x1B + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[7].input + 0x84 + 0x1B + + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[0].input + 0x94 + 0x1C + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[0].input + 0x84 + 0x1C + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[1].input + 0x94 + 0x1D + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[1].input + 0x84 + 0x1D + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[2].input + 0x94 + 0x1E + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[2].input + 0x84 + 0x1E + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[3].input + 0x94 + 0x1F + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[3].input + 0x84 + 0x1F + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[4].input + 0x94 + 0x20 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[4].input + 0x84 + 0x20 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[5].input + 0x94 + 0x21 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[5].input + 0x84 + 0x21 + + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[6].input + 0x94 + 0x22 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[6].input + 0x84 + 0x22 + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[7].input + 0x94 + 0x23 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.pads[7].input + 0x84 + 0x23 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[0].input + 0x95 + 0x14 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[0].input + 0x85 + 0x14 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[1].input + 0x95 + 0x15 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[1].input + 0x85 + 0x15 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[2].input + 0x95 + 0x16 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[2].input + 0x85 + 0x16 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[3].input + 0x95 + 0x17 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[3].input + 0x85 + 0x17 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[4].input + 0x95 + 0x18 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[4].input + 0x85 + 0x18 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[5].input + 0x95 + 0x19 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[5].input + 0x85 + 0x19 + + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[6].input + 0x95 + 0x1A + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[6].input + 0x85 + 0x1A + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[7].input + 0x95 + 0x1B + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[7].input + 0x85 + 0x1B + + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[0].input + 0x95 + 0x1C + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[0].input + 0x85 + 0x1C + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[1].input + 0x95 + 0x1D + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[1].input + 0x85 + 0x1D + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[2].input + 0x95 + 0x1E + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[2].input + 0x85 + 0x1E + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[3].input + 0x95 + 0x1F + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[3].input + 0x85 + 0x1F + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[4].input + 0x95 + 0x20 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[4].input + 0x85 + 0x20 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[5].input + 0x95 + 0x21 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[5].input + 0x85 + 0x21 + + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[6].input + 0x95 + 0x22 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[6].input + 0x85 + 0x22 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[7].input + 0x95 + 0x23 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.pads[7].input + 0x85 + 0x23 + + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.parameterRight.input + 0x95 + 0x29 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.parameterRight.input + 0x85 + 0x29 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.parameterLeft.input + 0x95 + 0x28 + + + + + + + ReloopReady.components.rightDeck.padUnit.currentLayer.parameterLeft.input + 0x85 + 0x28 + + + + + + + + ReloopReady.components.rightDeck.padUnit.modeButton.input + 0x91 + 0x20 + + + + + + + ReloopReady.components.rightDeck.padUnit.modeButton.input + 0x81 + 0x20 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[0].input + 0x95 + 0x00 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[0].input + 0x85 + 0x00 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[1].input + 0x95 + 0x05 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[1].input + 0x85 + 0x05 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[2].input + 0x95 + 0x0E + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[2].input + 0x85 + 0x0E + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[3].input + 0x95 + 0x0B + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[3].input + 0x85 + 0x0B + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[4].input + 0x95 + 0x0F + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[4].input + 0x85 + 0x0F + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[5].input + 0x95 + 0x09 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[5].input + 0x85 + 0x09 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[6].input + 0x95 + 0x08 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[6].input + 0x85 + 0x08 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[7].input + 0x95 + 0x12 + + + + + + + ReloopReady.components.rightDeck.padUnit.padModeSelectors[7].input + 0x85 + 0x12 + + + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.parameterRight.input + 0x94 + 0x29 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.parameterRight.input + 0x84 + 0x29 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.parameterLeft.input + 0x94 + 0x28 + + + + + + + ReloopReady.components.leftDeck.padUnit.currentLayer.parameterLeft.input + 0x84 + 0x28 + + + + + + + ReloopReady.components.leftDeck.padUnit.modeButton.input + 0x90 + 0x20 + + + + + + + ReloopReady.components.leftDeck.padUnit.modeButton.input + 0x80 + 0x20 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[0].input + 0x94 + 0x00 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[0].input + 0x84 + 0x00 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[1].input + 0x94 + 0x05 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[1].input + 0x84 + 0x05 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[2].input + 0x94 + 0x0E + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[2].input + 0x84 + 0x0E + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[3].input + 0x94 + 0x0B + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[3].input + 0x84 + 0x0B + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[4].input + 0x94 + 0x0F + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[4].input + 0x84 + 0x0F + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[5].input + 0x94 + 0x09 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[5].input + 0x84 + 0x09 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[6].input + 0x94 + 0x08 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[6].input + 0x84 + 0x08 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[7].input + 0x94 + 0x12 + + + + + + + ReloopReady.components.leftDeck.padUnit.padModeSelectors[7].input + 0x84 + 0x12 + + + + + + + + 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..3ffe808eff9c --- /dev/null +++ b/res/controllers/Reloop-Ready-scripts.js @@ -0,0 +1,875 @@ +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, +}; + + +/** + * 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) { + + var b = (color & 3) << 6; // ES3 does not support binary literals + var g = (color >> 2 & 3) << 6; + var r = (color >> 4 & 3) << 6; + var i = color >> 5 & 1; + + if (i === 0) { + // half the RGB intensity + r >> 1; + g >> 1; + b >> 1; + } + 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, function(color) { + var litColor = ReloopReady.padColorMapper.getValueForNearestColor(color); + var dimColor = litColor & 0x3F; // dim color by stripping the "intensity bit" + return { + lit: litColor, + dim: dimColor, + }; + }); + +})(); + +components.Button.prototype.sendShifted = true; +components.Button.prototype.shiftControl = true; +// shift control offset depends on concrete control + +components.Encoder.prototype.inValueScale = function(value) { + 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; + +/** + * creates an this.isPress guarded input handler + * @param {(value: number) => void} func callback that is called on ButtonDown + */ +ReloopReady.makeButtonDownInputHandler = function(func) { + return function(channel, control, value, status, _group) { + if (!this.isPress(channel, control, value, status)) { + return; + } + func.call(this, value); + }; +}; + +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(); + + this.components.leftDeck = new ReloopReady.Deck(0); + this.components.rightDeck = new ReloopReady.Deck(1); + this.components.leftChannel = new ReloopReady.Channel(0); + this.components.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(); + } + }, + }); + + // request controls status per standard serato sysex + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); +}; + +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, + }); + + 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 = _.map(_.range(0x00, 0x03), function(i) { + return 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 { + // TODO: For 2.4 using plain beatloop_activate + // is sufficient, see #4328 + if (engine.getValue(this.group, "loop_enabled")) { + script.triggerControl(this.group, "reloop_toggle"); + } else { + script.triggerControl(this.group, "beatloop_activate"); + } + } + } + }, + }) + }; + + +}; + +ReloopReady.PadMode = function(obj) { + components.ComponentContainer.call(this, obj); + // interpret this an interface definition + this.pads = Array(8); + this.parameterLeft = new components.Button(); + this.parameterRight = new components.Button(); +}; +ReloopReady.PadMode.prototype = Object.create(components.ComponentContainer.prototype); + +ReloopReady.HotcuePadMode = function(index) { + ReloopReady.PadMode.call(this); + + this.pads = _.map(this.pads, function(_pads, i) { + return new components.HotcueButton({ + midi: [0x94 + index, 0x14 + i], + group: "[Channel" + (index + 1) + "]", + shiftOffset: 0x8, + off: 0x00, + number: i + 1, + colorMapper: ReloopReady.padColorMapper, + outConnect: false, + }); + }); +}; + +ReloopReady.HotcuePadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + +ReloopReady.AutoLoopPadMode = function(index) { + ReloopReady.PadMode.call(this); + + this.currentLoopSizeExp = -2; + var theContainer = this; + + var clampLoopSizeExp = function(loopSizeExp) { + return _.clamp(loopSizeExp, -5, -2); + }; + + this.setLoopSizes = _.bind(function(loopSizeExp) { + _(_.range(loopSizeExp, loopSizeExp + 8)) + .map(function(exp) { return Math.pow(2, exp); }) + .zip(this.pads) + .forEach(function(arr) { + var size = arr[0]; + var pad = arr[1]; + pad.disconnect(); + pad.inKey = "beatloop_" + size + "_toggle"; + pad.outKey = "beatloop_" + size + "_enabled"; + pad.connect(); + pad.trigger(); + }); + }, this); + + for (var i = 0; i < this.pads.length; i++) { + this.pads[i] = new components.Button({ + midi: [0x94 + index, 0x14 + i], + group: "[Channel" + (index + 1) + "]", + shiftOffset: 0x8, + off: ReloopReady.padColorPalette.Red.dim, + on: ReloopReady.padColorPalette.Red.lit, + outConnect: false, + }); + } + + var makeParameterInputHandler = function(loopSizeChangeAmount) { + return function(channel, control, value, status, _group) { + var pressed = this.isPress(channel, control, value, status); + if (pressed) { + var newLoopSize = clampLoopSizeExp(theContainer.currentLoopSizeExp + loopSizeChangeAmount); + if (newLoopSize !== theContainer.currentLoopSizeExp) { + theContainer.currentLoopSizeExp = newLoopSize; + theContainer.setLoopSizes(newLoopSize); + } + } + this.output(pressed); + }; + }; + + this.parameterLeft = new components.Button({ + midi: [0x94 + index, 0x28], + shiftOffset: 0x2, + input: makeParameterInputHandler(-1), + }); + this.parameterRight = new components.Button({ + midi: [0x94 + index, 0x29], + shiftOffset: 0x2, + input: makeParameterInputHandler(1), + }); + + this.setLoopSizes(this.currentLoopSizeExp); +}; + +ReloopReady.AutoLoopPadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + +ReloopReady.ManualLoopPadMode = function(index) { + ReloopReady.PadMode.call(this); + + var loopMoveBeats = 4; + var group = "[Channel" + (index + 1) + "]"; + + this.pads[0] = new components.Button({ + key: "loop_in", + on: ReloopReady.padColorPalette.Blue.lit, + off: ReloopReady.padColorPalette.Blue.dim, + }); + this.pads[1] = new components.Button({ + key: "loop_out", + on: ReloopReady.padColorPalette.Blue.lit, + off: ReloopReady.padColorPalette.Blue.dim, + }); + this.pads[2] = new components.Button({ + inKey: "reloop_toggle", + outKey: "loop_enabled", + on: ReloopReady.padColorPalette.Red.lit, + off: ReloopReady.padColorPalette.Red.dim, + }); + this.pads[3] = new components.Button({ + key: "loop_in_goto", + on: ReloopReady.padColorPalette.Red.lit, + off: ReloopReady.padColorPalette.Red.dim, + input: function(channel, control, value, status, _group) { + if (!this.isPress(channel, control, value, status)) { + return; + } + if (engine.getValue(this.group, "loop_enabled")) { + engine.setValue(this.group, "loop_enabled", false); + } else { + this.inSetValue(true); + } + }, + }); + this.pads[4] = new components.Button({ + key: "loop_halve", + on: ReloopReady.padColorPalette.Green.lit, + off: ReloopReady.padColorPalette.Green.dim, + }); + this.pads[5] = new components.Button({ + key: "loop_double", + on: ReloopReady.padColorPalette.Green.dim, + off: ReloopReady.padColorPalette.Green.dim, + }); + this.pads[6] = new components.Button({ + key: "loop_move", + on: ReloopReady.padColorPalette.Cyan.dim, + off: ReloopReady.padColorPalette.Cyan.dim, + unshift: function() { + this.input = ReloopReady.makeButtonDownInputHandler(function() { + this.inSetValue(loopMoveBeats); + }); + }, + shift: function() { + this.input = ReloopReady.makeButtonDownInputHandler(function() { + this.inSetValue(engine.getValue(this.group, "loop_size")); + }); + }, + }); + this.pads[7] = new components.Button({ + key: "loop_move", + on: ReloopReady.padColorPalette.Cyan.lit, + off: ReloopReady.padColorPalette.Cyan.dim, + unshift: function() { + this.input = ReloopReady.makeButtonDownInputHandler(function() { + this.inSetValue(-loopMoveBeats); + }); + }, + shift: function() { + this.input = ReloopReady.makeButtonDownInputHandler(function() { + this.inSetValue(-engine.getValue(this.group, "loop_size")); + }); + }, + }); + + _.forEach(this.pads, function(c, i) { + c.midi = [0x94 + index, 0x14 + i]; + }); + + this.parameterLeft = new components.Button({ + midi: [0x94 + index, 0x28], + shiftOffset: 0x2, + input: ReloopReady.makeButtonDownInputHandler(function() { + loopMoveBeats *= 0.5; + }), + }); + this.parameterRight = new components.Button({ + midi: [0x94 + index, 0x29], + shiftOffset: 0x2, + input: ReloopReady.makeButtonDownInputHandler(function() { + loopMoveBeats *= 2; + }), + }); + + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = group; + } + }); +}; +ReloopReady.ManualLoopPadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + + +ReloopReady.SamplerPadMode = function(index) { + ReloopReady.PadMode.call(this, index); + + // var baseOffset = index * 8; + + this.pads = _.map(this.pads, function(_pads, i) { + return new components.SamplerButton({ + midi: [0x94 + index, 0x14 + i], + // number: baseOffset + i + 1, + number: i + 1, + shiftOffset: 0x8, + off: 0x00, + outConnect: false, + }); + }); +}; +ReloopReady.SamplerPadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + + +ReloopReady.LoopRollPadMode = function(index) { + ReloopReady.PadMode.call(this); + + this.currentLoopSizeExp = -2; + var theContainer = this; + + var clampLoopSizeExp = function(loopSizeExp) { + return _.clamp(loopSizeExp, -5, -2); + }; + + this.setLoopSizes = _.bind(function(loopSizeExp) { + _(_.range(loopSizeExp, loopSizeExp + 8)) + .map(function(exp) { return Math.pow(2, exp); }) + .zip(this.pads) + .forEach(function(arr) { + var size = arr[0]; + var pad = arr[1]; + pad.disconnect(); + pad.inKey = "beatlooproll_" + size + "_activate"; + pad.outKey = "beatloop_" + size + "_enabled"; + pad.connect(); + pad.trigger(); + }); + }, this); + + for (var i = 0; i < this.pads.length; i++) { + this.pads[i] = new components.Button({ + midi: [0x94 + index, 0x14 + i], + group: "[Channel" + (index + 1) + "]", + shiftOffset: 0x8, + off: ReloopReady.padColorPalette.Green.dim, + on: ReloopReady.padColorPalette.Green.lit, + outConnect: false, + }); + } + + var makeParameterInputHandler = function(loopSizeChangeAmount) { + return function(channel, control, value, status, _group) { + var pressed = this.isPress(channel, control, value, status); + if (pressed) { + var newLoopSize = clampLoopSizeExp(theContainer.currentLoopSizeExp + loopSizeChangeAmount); + if (newLoopSize !== theContainer.currentLoopSizeExp) { + theContainer.currentLoopSizeExp = newLoopSize; + theContainer.setLoopSizes(newLoopSize); + } + } + this.output(pressed); + }; + }; + + this.parameterLeft = new components.Button({ + midi: [0x94 + index, 0x28], + shiftOffset: 0x2, + input: makeParameterInputHandler(-1), + }); + this.parameterRight = new components.Button({ + midi: [0x94 + index, 0x29], + shiftOffset: 0x2, + input: makeParameterInputHandler(1), + }); + + this.setLoopSizes(this.currentLoopSizeExp); +}; + +ReloopReady.LoopRollPadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + +ReloopReady.BeatGridPadMode = function(index) { + ReloopReady.PadMode.call(this); + + var group = "[Channel" + (index + 1) + "]"; + + this.pads[0] = new components.Button({ + key: "beats_translate_earlier", + on: ReloopReady.padColorPalette.Blue.lit, + off: ReloopReady.padColorPalette.Blue.dim, + }); + this.pads[1] = new components.Button({ + key: "beats_translate_later", + on: ReloopReady.padColorPalette.Blue.lit, + off: ReloopReady.padColorPalette.Blue.dim, + }); + this.pads[2] = new components.Button({ + key: "beats_translate_faster", + on: ReloopReady.padColorPalette.Red.lit, + off: ReloopReady.padColorPalette.Red.dim, + }); + this.pads[3] = new components.Button({ + key: "beats_translate_slower", + on: ReloopReady.padColorPalette.Red.lit, + off: ReloopReady.padColorPalette.Red.dim, + }); + this.pads[4] = new components.Button({ + key: "shift_cues_earlier", + on: ReloopReady.padColorPalette.Green.lit, + off: ReloopReady.padColorPalette.Green.dim, + }); + this.pads[5] = new components.Button({ + key: "shift_cues_later", + on: ReloopReady.padColorPalette.Green.dim, + off: ReloopReady.padColorPalette.Green.dim, + }); + this.pads[6] = new components.Button({ + key: "bpm_tap", + on: ReloopReady.padColorPalette.Cyan.dim, + off: ReloopReady.padColorPalette.Cyan.dim, + }); + this.pads[7] = new components.Button({ + key: "beats_translate_curpos", + on: ReloopReady.padColorPalette.Cyan.lit, + off: ReloopReady.padColorPalette.Cyan.dim, + }); + + _.forEach(this.pads, function(c, i) { + c.midi = [0x94 + index, 0x14 + i]; + }); + + this.parameterLeft = new components.Button({ + midi: [0x94 + index, 0x28], + shiftOffset: 0x2 + }); + this.parameterRight = new components.Button({ + midi: [0x94 + index, 0x29], + shiftOffset: 0x2 + }); + + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = group; + } + }); +}; +ReloopReady.BeatGridPadMode.prototype = Object.create(ReloopReady.PadMode.prototype); + + +// Ordering of array elements determines layout of pad mode selectors. +ReloopReady.controlPadModeAssoc = [ + {pos: 0, control: 0x00, mode: ReloopReady.HotcuePadMode}, + {pos: 1, control: 0x05, mode: ReloopReady.AutoLoopPadMode}, + {pos: 2, control: 0x0E, mode: ReloopReady.ManualLoopPadMode}, + {pos: 3, control: 0x0B, mode: ReloopReady.SamplerPadMode}, + // {pos: 4, control: 0x0F, mode: ReloopReady.Pitch, TODO }, + // {pos: 5, control: 0x09, mode: "SCRATCH BANK", TODO }, + {pos: 6, control: 0x08, mode: ReloopReady.LoopRollPadMode}, + {pos: 7, control: 0x12, mode: ReloopReady.BeatGridPadMode}, +]; + +ReloopReady.PadContainer = function(index) { + + // parent constructor is called later + + components.ComponentContainer.call(this); + + // construct instance of each mode per Container + var padModeInstances = _.map(ReloopReady.controlPadModeAssoc, function(obj) { + var modeInstance = new (obj.mode)(index); + // make sure no multiple components have "ownership" over each pad + modeInstance.forEachComponent(function(c) { + c.disconnect(); + }); + return { + pos: obj.pos, + control: obj.control, + modeInstance: modeInstance, + }; + }); + + this.currentLayer = padModeInstances[0].modeInstance; + this.currentLayer.forEachComponent(function(component) { + component.connect(); + component.trigger(); + }); + + var thisContainer = this; + + var applyLayer = function(layer) { + if (thisContainer.currentLayer === layer) { + return; + } + + thisContainer.currentLayer.forEachComponent(function(component) { + component.disconnect(); + }); + + if (thisContainer.isShifted) { + layer.shift(); + } else { + layer.unshift(); + } + + layer.forEachComponent(function(component) { + component.connect(); + component.trigger(); + }); + + thisContainer.currentLayer = layer; + + _.forEach(thisContainer.padModeSelectors, function(selector) { + selector.trigger(); + }); + }; + + // factory/HO function for creating input handlers that change the padmode + // this expects to be used as for creating the input handler of a + // components.Button + var makePadModeInputHandler = function(layer) { + return (layer === undefined) ? + function(_channel, _control, _value, _status, _group) {} : + function(channel, control, value, status, _group) { + if (!this.isPress(channel, control, value, status)) { + return; + } + applyLayer(layer); + }; + }; + + + // create physical buttons for changing the layers + this.padModeSelectors = Array(8); + _.forEach(padModeInstances, function(obj) { + thisContainer.padModeSelectors[obj.pos] = new components.Button({ + midi: [0x94 + index, obj.control], + on: ReloopReady.padColorPalette.Blue.lit, + off: ReloopReady.padColorPalette.Blue.dim, + input: makePadModeInputHandler(obj.modeInstance), + trigger: function() { + this.output(thisContainer.currentLayer === obj.modeInstance); + } + }); + }); + this.padModeSelectors = _.map(this.padModeSelectors, function(obj) { + // for mixxx 2.4: + // return obj ?? new components.Button({}); + return (obj === undefined) ? new components.Button({}) : obj; + }); + + // button can not be controlled from software. + // This component instance just serves as input handler for debugging. + this.modeButton = new components.Button({ + midi: [index, 0x20], + input: function(_channel, _control, _value, _status, _group) { + } + }); +}; + +ReloopReady.PadContainer.prototype = Object.create(components.ComponentContainer.prototype); + +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, + }); // TODO 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.PadContainer(index); + + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = thisDeck.currentDeck; + } + }); +}; + +ReloopReady.Deck.prototype = new components.Deck();