diff --git a/res/controllers/Numark Mixtrack Pro FX.midi.xml b/res/controllers/Numark Mixtrack Pro FX.midi.xml new file mode 100644 index 00000000000..3cac016a09a --- /dev/null +++ b/res/controllers/Numark Mixtrack Pro FX.midi.xml @@ -0,0 +1,2143 @@ + + + + Numark Mixtrack Pro FX + h67ma, bad1dea5, photoenix + Mapping for the Numark Mixtrack Pro FX + https://mixxx.discourse.group/t/numark-mixtrack-pro-fx/19561 + numark_mixtrack_pro_fx + + + + + + + + + + + [Master] + MixtrackProFX.gains.mainGain.input + 0xBE + 0x23 + + + + + + + + [Master] + crossfader + 0xBF + 0x08 + + + + + + + + [Master] + crossfader + 0xB1 + 0x08 + + + + + + + [Channel1] + MixtrackProFX.deck[0].gain.input + 0xB0 + 0x16 + + + + + + [Channel2] + MixtrackProFX.deck[1].gain.input + 0xB1 + 0x16 + + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackProFX.deck[0].treble.input + 0xB0 + 0x17 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackProFX.deck[1].treble.input + 0xB1 + 0x17 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackProFX.deck[0].mid.input + 0xB0 + 0x18 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackProFX.deck[1].mid.input + 0xB1 + 0x18 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackProFX.deck[0].bass.input + 0xB0 + 0x19 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackProFX.deck[1].bass.input + 0xB1 + 0x19 + + + + + + + [QuickEffectRack1_[Channel1]] + MixtrackProFX.deck[0].filter.input + 0xB0 + 0x1A + + + + + + [QuickEffectRack1_[Channel2]] + MixtrackProFX.deck[1].filter.input + 0xB1 + 0x1A + + + + + + + [Channel1] + MixtrackProFX.deck[0].volume.input + 0xB0 + 0x1C + + + + + + [Channel2] + MixtrackProFX.deck[1].volume.input + 0xB1 + 0x1C + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitch.inputMSB + 0xB0 + 0x09 + + + + + + [Channel2] + MixtrackProFX.deck[1].pitch.inputMSB + 0xB1 + 0x09 + + + + + + [Channel1] + MixtrackProFX.deck[0].pitch.inputLSB + 0xB0 + 0x29 + + + + + + [Channel2] + MixtrackProFX.deck[1].pitch.inputLSB + 0xB1 + 0x29 + + + + + + + [Channel1] + MixtrackProFX.deck[0].syncButton.input + 0x90 + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].syncButton.input + 0x91 + 0x02 + + + + + + + [Channel1] + MixtrackProFX.deck[0].syncButton.input + 0x80 + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].syncButton.input + 0x81 + 0x02 + + + + + + + [Channel1] + MixtrackProFX.deck[0].syncButton.input + 0x90 + 0x03 + + + + + + [Channel2] + MixtrackProFX.deck[1].syncButton.input + 0x91 + 0x03 + + + + + + + [Channel1] + MixtrackProFX.deck[0].syncButton.input + 0x80 + 0x03 + + + + + + [Channel2] + MixtrackProFX.deck[1].syncButton.input + 0x81 + 0x03 + + + + + + + [Channel1] + MixtrackProFX.deck[0].cueButton.input + 0x90 + 0x01 + + + + + + [Channel2] + MixtrackProFX.deck[1].cueButton.input + 0x91 + 0x01 + + + + + + + [Channel1] + MixtrackProFX.deck[0].cueButton.input + 0x80 + 0x01 + + + + + + [Channel2] + MixtrackProFX.deck[1].cueButton.input + 0x81 + 0x01 + + + + + + + [Channel1] + MixtrackProFX.deck[0].cueButton.input + 0x90 + 0x05 + + + + + + [Channel2] + MixtrackProFX.deck[1].cueButton.input + 0x91 + 0x05 + + + + + + + [Channel1] + MixtrackProFX.deck[0].cueButton.input + 0x80 + 0x05 + + + + + + [Channel2] + MixtrackProFX.deck[1].cueButton.input + 0x81 + 0x05 + + + + + + + [Channel1] + MixtrackProFX.deck[0].playButton.input + 0x90 + 0x00 + + + + + + [Channel2] + MixtrackProFX.deck[1].playButton.input + 0x91 + 0x00 + + + + + + + [Channel1] + MixtrackProFX.deck[0].playButton.input + 0x80 + 0x00 + + + + + + [Channel2] + MixtrackProFX.deck[1].playButton.input + 0x81 + 0x00 + + + + + + + [Channel1] + MixtrackProFX.deck[0].playButton.input + 0x90 + 0x04 + + + + + + [Channel2] + MixtrackProFX.deck[1].playButton.input + 0x91 + 0x04 + + + + + + + [Channel1] + MixtrackProFX.deck[0].playButton.input + 0x80 + 0x04 + + + + + + [Channel2] + MixtrackProFX.deck[1].playButton.input + 0x81 + 0x04 + + + + + + + [Channel1] + MixtrackProFX.deck[0].shiftButton.input + 0x90 + 0x20 + + + + + + [Channel2] + MixtrackProFX.deck[1].shiftButton.input + 0x91 + 0x20 + + + + + + + [Channel1] + MixtrackProFX.deck[0].shiftButton.input + 0x80 + 0x20 + + + + + + [Channel2] + MixtrackProFX.deck[1].shiftButton.input + 0x81 + 0x20 + + + + + + + [Channel1] + MixtrackProFX.deck[0].scratchToggle.input + 0x90 + 0x07 + + + + + + [Channel2] + MixtrackProFX.deck[1].scratchToggle.input + 0x91 + 0x07 + + + + + + + [Channel1] + MixtrackProFX.deck[0].scratchToggle.input + 0x80 + 0x07 + + + + + + [Channel2] + MixtrackProFX.deck[1].scratchToggle.input + 0x81 + 0x07 + + + + + + + [Channel1] + MixtrackProFX.deck[0].scratchToggle.input + 0x90 + 0x08 + + + + + + [Channel2] + MixtrackProFX.deck[1].scratchToggle.input + 0x91 + 0x08 + + + + + + + [Channel1] + MixtrackProFX.deck[0].scratchToggle.input + 0x80 + 0x08 + + + + + + [Channel2] + MixtrackProFX.deck[1].scratchToggle.input + 0x81 + 0x08 + + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x00 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x00 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x0D + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x0D + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x07 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x07 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x0B + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x0B + + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x00 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x00 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x0D + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x0D + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x07 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x07 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x0B + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x0B + + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x02 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x94 + 0x0F + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x95 + 0x0F + + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x02 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.modeButtonPress + 0x84 + 0x0F + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.modeButtonPress + 0x85 + 0x0F + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x14 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x14 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x15 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x15 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x16 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x16 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x17 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x17 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x18 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x18 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x19 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x19 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1A + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1A + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1B + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1B + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x14 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x14 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x15 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x15 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x16 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x16 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x17 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x17 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x18 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x18 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x19 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x19 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1A + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1A + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1B + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1B + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1C + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1C + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1D + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1D + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1E + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1E + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x1F + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x1F + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x20 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x20 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x21 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x21 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x22 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x22 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x94 + 0x23 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x95 + 0x23 + + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1C + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1C + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1D + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1D + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1E + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1E + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x1F + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x1F + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x20 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x20 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x21 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x21 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x22 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x22 + + + + + + [Channel1] + MixtrackProFX.deck[0].padSection.padPress + 0x84 + 0x23 + + + + + + [Channel2] + MixtrackProFX.deck[1].padSection.padPress + 0x85 + 0x23 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loop.input + 0x94 + 0x40 + + + + + + [Channel2] + MixtrackProFX.deck[1].loop.input + 0x95 + 0x40 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loop.input + 0x84 + 0x40 + + + + + + [Channel2] + MixtrackProFX.deck[1].loop.input + 0x85 + 0x40 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loop.input + 0x94 + 0x41 + + + + + + [Channel2] + MixtrackProFX.deck[1].loop.input + 0x95 + 0x41 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loop.input + 0x84 + 0x41 + + + + + + [Channel2] + MixtrackProFX.deck[1].loop.input + 0x85 + 0x41 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopHalf.input + 0x94 + 0x34 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopHalf.input + 0x95 + 0x34 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopHalf.input + 0x84 + 0x34 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopHalf.input + 0x85 + 0x34 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopHalf.input + 0x94 + 0x36 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopHalf.input + 0x95 + 0x36 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopHalf.input + 0x84 + 0x36 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopHalf.input + 0x85 + 0x36 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopDouble.input + 0x94 + 0x35 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopDouble.input + 0x95 + 0x35 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopDouble.input + 0x84 + 0x35 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopDouble.input + 0x85 + 0x35 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopDouble.input + 0x94 + 0x37 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopDouble.input + 0x95 + 0x37 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loopDouble.input + 0x84 + 0x37 + + + + + + [Channel2] + MixtrackProFX.deck[1].loopDouble.input + 0x85 + 0x37 + + + + + + + [Channel1] + MixtrackProFX.wheelTurn + 0xB0 + 0x06 + + + + + + [Channel2] + MixtrackProFX.wheelTurn + 0xB1 + 0x06 + + + + + + + [Channel1] + MixtrackProFX.wheelTouch + 0x90 + 0x06 + + + + + + [Channel2] + MixtrackProFX.wheelTouch + 0x91 + 0x06 + + + + + + + [Library] + MixtrackProFX.browse.knob.input + 0xBF + 0x00 + + + + + + + [Library] + MixtrackProFX.browse.knob.input + 0xBF + 0x01 + + + + + + + [Library] + MixtrackProFX.browse.knobButton.input + 0x9F + 0x07 + + + + + + + [Library] + MixtrackProFX.browse.knobButton.input + 0x8F + 0x07 + + + + + + + [Library] + MixtrackProFX.browse.knobButton.input + 0x9F + 0x06 + + + + + + + [Library] + MixtrackProFX.browse.knobButton.input + 0x8F + 0x06 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loadButton.input + 0x9F + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].loadButton.input + 0x9F + 0x03 + + + + + + + [Channel1] + MixtrackProFX.deck[0].loadButton.input + 0x8F + 0x02 + + + + + + [Channel2] + MixtrackProFX.deck[1].loadButton.input + 0x8F + 0x03 + + + + + + + [EffectRack1_EffectUnit1] + MixtrackProFX.effect[0].dryWetKnob.input + 0xB8 + 0x04 + + + + + + [EffectRack1_EffectUnit2] + MixtrackProFX.effect[1].dryWetKnob.input + 0xB8 + 0x04 + + + + + + + [EffectRack1_EffectUnit1] + MixtrackProFX.effect[0].effectParam.input + 0xB8 + 0x05 + + + + + + [EffectRack1_EffectUnit2] + MixtrackProFX.effect[1].effectParam.input + 0xB8 + 0x05 + + + + + + + [Channel1] + MixtrackProFX.deck[0].tap.input + 0x98 + 0x09 + + + + + + [Channel2] + MixtrackProFX.deck[1].tap.input + 0x99 + 0x09 + + + + + + + [Channel1] + MixtrackProFX.deck[0].tap.input + 0x88 + 0x09 + + + + + + [Channel2] + MixtrackProFX.deck[1].tap.input + 0x89 + 0x09 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackProFX.effect[0].prevEffect.input + 0x98 + 0x00 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackProFX.effect[0].prevEffect.input + 0x88 + 0x00 + + + + + + + [Library] + MixtrackProFX.deck[0].setBeatgrid.input + 0x98 + 0x01 + + + + + + + [Library] + MixtrackProFX.deck[0].setBeatgrid.input + 0x88 + 0x01 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackProFX.effect[1].prevEffect.input + 0x98 + 0x02 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackProFX.effect[1].prevEffect.input + 0x88 + 0x02 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackProFX.effect[0].nextEffect.input + 0x99 + 0x03 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackProFX.effect[0].nextEffect.input + 0x89 + 0x03 + + + + + + + [Channel2] + MixtrackProFX.deck[1].setBeatgrid.input + 0x99 + 0x04 + + + + + + + [Channel2] + MixtrackProFX.deck[1].setBeatgrid.input + 0x89 + 0x04 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackProFX.effect[1].nextEffect.input + 0x99 + 0x05 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackProFX.effect[1].nextEffect.input + 0x89 + 0x05 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackProFX.effect[0].enableSwitch.input + 0xB8 + 0x03 + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackProFX.effect[1].enableSwitch.input + 0xB9 + 0x03 + + + + + + + [Channel1] + MixtrackProFX.deck[0].pflButton.input + 0x90 + 0x1B + + + + + + [Channel2] + MixtrackProFX.deck[1].pflButton.input + 0x91 + 0x1B + + + + + + + [Channel1] + MixtrackProFX.deck[0].pflButton.input + 0x80 + 0x1B + + + + + + [Channel2] + MixtrackProFX.deck[1].pflButton.input + 0x81 + 0x1B + + + + + + + [Master] + MixtrackProFX.gains.cueGain.input + 0xBE + 0x2F + + + + + + + [Master] + MixtrackProFX.gains.cueMix.input + 0xBE + 0x27 + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendDown.input + 0x90 + 0x0C + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendDown.input + 0x91 + 0x0C + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendDown.input + 0x80 + 0x0C + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendDown.input + 0x81 + 0x0C + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendDown.input + 0x90 + 0x2C + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendDown.input + 0x91 + 0x2C + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendDown.input + 0x80 + 0x2C + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendDown.input + 0x81 + 0x2C + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendUp.input + 0x90 + 0x0B + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendUp.input + 0x91 + 0x0B + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendUp.input + 0x80 + 0x0B + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendUp.input + 0x81 + 0x0B + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendUp.input + 0x90 + 0x2B + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendUp.input + 0x91 + 0x2B + + + + + + + [Channel1] + MixtrackProFX.deck[0].pitchBendUp.input + 0x80 + 0x2B + + + + + + [Channel2] + MixtrackProFX.deck[1].pitchBendUp.input + 0x81 + 0x2B + + + + + + + diff --git a/res/controllers/Numark-Mixtrack-Pro-FX-scripts.js b/res/controllers/Numark-Mixtrack-Pro-FX-scripts.js new file mode 100644 index 00000000000..29b9b76d7b3 --- /dev/null +++ b/res/controllers/Numark-Mixtrack-Pro-FX-scripts.js @@ -0,0 +1,795 @@ +var MixtrackProFX = {}; + +// pitch ranges +// add/remove/modify steps to your liking +// default step must be set in Mixxx settings +// setting is stored per deck in pitchRange.currentRangeIdx +MixtrackProFX.pitchRanges = [0.08, 0.16, 1]; + +// whether the corresponding Mixxx option is enabled +// (Settings -> Preferences -> Waveforms -> Synchronize zoom level across all waveforms) +MixtrackProFX.waveformsSynced = true; + +// jogwheel +MixtrackProFX.jogScratchSensitivity = 1024; +MixtrackProFX.jogScratchAlpha = 1; // do NOT set to 2 or higher +MixtrackProFX.jogScratchBeta = 1/32; +MixtrackProFX.jogPitchSensitivity = 10; +MixtrackProFX.jogSeekSensitivity = 10000; + +// blink settings +MixtrackProFX.enableBlink = true; +MixtrackProFX.blinkDelay = 700; + +// autoloop sizes, for available values see: +// https://manual.mixxx.org/2.3/en/chapters/appendix/mixxx_controls.html#control-[ChannelN]-beatloop_X_toggle +MixtrackProFX.autoLoopSizes = [ + "0.0625", + "0.125", + "0.25", + "0.5", + "1", + "2", + "4", + "8" +]; + +// beatjump values, for available values see: +// https://manual.mixxx.org/2.3/en/chapters/appendix/mixxx_controls.html#control-[ChannelN]-beatjump_X_forward +// underscores (_) at the end are needed because numeric values (e.g. 8) have two underscores (e.g. beatjump_8_forward), +// but "beatjump_forward"/"beatjump_backward" have only one underscore +MixtrackProFX.beatJumpValues = [ + "0.0625_", + "0.125_", + "0.25_", + "0.5_", + "1_", + "2_", + "", // "beatjump_forward"/"beatjump_backward" - jump by the value selected in Mixxx GUI (4 by default) + "8_" +]; + +// dim all lights when inactive instead of turning them off +components.Button.prototype.off = 0x01; + +// pad modes control codes +MixtrackProFX.PadModeControls = { + HOTCUE: 0x00, + AUTOLOOP: 0x0D, + FADERCUTS: 0x07, + SAMPLE1: 0x0B, + BEATJUMP: 0x02, + SAMPLE2: 0x0F +}; + +// state variable, don't touch +MixtrackProFX.shifted = false; + +MixtrackProFX.init = function() { + // disable demo lightshow + var exitDemoSysex = [0xF0, 0x7E, 0x00, 0x06, 0x01, 0xF7]; + midi.sendSysexMsg(exitDemoSysex, exitDemoSysex.length); + + // enables 4 bottom pads "fader cuts" + var faderCutSysex = [0xF0, 0x00, 0x20, 0x7F, 0x03, 0xF7]; + midi.sendSysexMsg(faderCutSysex, faderCutSysex.length); + + // initialize component containers + MixtrackProFX.deck = new components.ComponentContainer(); + MixtrackProFX.effect = new components.ComponentContainer(); + var i; + for (i = 0; i < 2; i++) { + MixtrackProFX.deck[i] = new MixtrackProFX.Deck(i + 1); + MixtrackProFX.effect[i] = new MixtrackProFX.EffectUnit(i + 1); + } + + MixtrackProFX.browse = new MixtrackProFX.Browse(); + MixtrackProFX.gains = new MixtrackProFX.Gains(); + + var statusSysex = [0xF0, 0x00, 0x20, 0x7F, 0x03, 0x01, 0xF7]; + midi.sendSysexMsg(statusSysex, statusSysex.length); + + engine.makeConnection("[Channel1]", "VuMeter", MixtrackProFX.vuCallback); + engine.makeConnection("[Channel2]", "VuMeter", MixtrackProFX.vuCallback); + + // trigger is needed to initialize lights to 0x01 + MixtrackProFX.deck.forEachComponent(function(component) { + component.trigger(); + }); + MixtrackProFX.effect.forEachComponent(function(component) { + component.trigger(); + }); +}; + +MixtrackProFX.shutdown = function() { + var shutdownSysex = [0xF0, 0x00, 0x20, 0x7F, 0x02, 0xF7]; + midi.sendSysexMsg(shutdownSysex, shutdownSysex.length); +}; + +MixtrackProFX.shift = function() { + MixtrackProFX.shifted = true; + MixtrackProFX.deck.shift(); + MixtrackProFX.browse.shift(); + MixtrackProFX.effect.shift(); +}; + +MixtrackProFX.unshift = function() { + MixtrackProFX.shifted = false; + MixtrackProFX.deck.unshift(); + MixtrackProFX.browse.unshift(); + MixtrackProFX.effect.unshift(); +}; + +// TODO in 2.3 it is not possible to "properly" map the FX selection buttons. +// this should be done with load_preset and QuickEffects instead (when effect +// chain preset saving/loading is available in Mixxx) +MixtrackProFX.EffectUnit = function(deckNumber) { + // switch values are: + // 0 - switch in the middle + // 1 - switch up + // 2 - switch down + this.enableSwitch = new components.Button({ + group: "[EffectRack1_EffectUnit" + deckNumber + "_Effect1]", + inKey: "enabled" + }); + + this.dryWetKnob = new components.Pot({ + group: "[EffectRack1_EffectUnit" + deckNumber + "]", + inKey: "mix" + }); + + this.effectParam = new components.Encoder({ + group: "[EffectRack1_EffectUnit" + deckNumber + "_Effect1]", + shift: function() { + this.inKey = "parameter2"; + }, + unshift: function() { + this.inKey = "parameter1"; + }, + input: function(channel, control, value) { + this.inSetParameter(this.inGetParameter() + this.inValueScale(value)); + }, + inValueScale: function(value) { + return (value < 0x40) ? 0.05 : -0.05; + } + }); + + this.prevEffect = new components.Button({ + midi: [0x98, (deckNumber - 1) * 2], + shift: function() { + this.disconnect(); + this.group = "[Channel" + deckNumber + "]"; + this.inKey = "pitch_up"; + this.outKey = "pitch_up"; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); + this.group = "[EffectRack1_EffectUnit" + deckNumber + "_Effect1]"; + this.inKey = "prev_effect"; + this.outKey = "prev_effect"; + this.connect(); + this.trigger(); + } + }); + + this.nextEffect = new components.Button({ + midi: [0x99, 0x03 + (deckNumber - 1) * 2], + shift: function() { + this.disconnect(); + this.group = "[Channel" + deckNumber + "]"; + this.inKey = "pitch_down"; + this.outKey = "pitch_down"; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); + this.group = "[EffectRack1_EffectUnit" + deckNumber + "_Effect1]"; + this.inKey = "next_effect"; + this.outKey = "next_effect"; + this.connect(); + this.trigger(); + } + }); +}; + +MixtrackProFX.EffectUnit.prototype = new components.ComponentContainer(); + +MixtrackProFX.Deck = function(number) { + components.Deck.call(this, number); + + var channel = number - 1; + var deck = this; + this.scratchModeEnabled = true; + + this.playButton = new components.PlayButton({ + midi: [0x90 + channel, 0x00], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x04 + }); + + this.cueButton = new components.CueButton({ + midi: [0x90 + channel, 0x01], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x04 + }); + + this.syncButton = new components.SyncButton({ + midi: [0x90 + channel, 0x02], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x01 + }); + + this.tap = new components.Button({ + key: "bpm_tap", + midi: [0x88, 0x09] + }); + + this.pflButton = new components.Button({ + type: components.Button.prototype.types.toggle, + midi: [0x90 + channel, 0x1B], + key: "pfl" + }); + + this.loadButton = new components.Button({ + inKey: "LoadSelectedTrack" + }); + + this.volume = new components.Pot({ + inKey: "volume" + }); + + this.treble = new components.Pot({ + group: "[EqualizerRack1_" + this.currentDeck + "_Effect1]", + inKey: "parameter3" + }); + + this.mid = new components.Pot({ + group: "[EqualizerRack1_" + this.currentDeck + "_Effect1]", + inKey: "parameter2" + }); + + this.bass = new components.Pot({ + group: "[EqualizerRack1_" + this.currentDeck + "_Effect1]", + inKey: "parameter1" + }); + + this.filter = new components.Pot({ + group: "[QuickEffectRack1_" + this.currentDeck + "]", + inKey: "super1" + }); + + this.gain = new components.Pot({ + inKey: "pregain" + }); + + this.pitch = new components.Pot({ + inKey: "rate", + invert: true + }); + + this.padSection = new MixtrackProFX.PadSection(number); + + this.shiftButton = new components.Button({ + input: function(channel, control, value) { + // each shift button shifts the entire controller. + // more consistent with the logic burned into hardware + if (this.isPress(channel, control, value)) { + MixtrackProFX.shift(); + } else { + MixtrackProFX.unshift(); + } + } + }); + + this.loop = new components.Button({ + outKey: "loop_enabled", + midi: [0x94 + channel, 0x40], + input: function(channel, control, value, status, group) { + if (!this.isPress(channel, control, value)) { + return; + } + + if (!MixtrackProFX.shifted) { + if (engine.getValue(group, "loop_enabled") === 0) { + script.triggerControl(group, "beatloop_activate"); + } else { + script.triggerControl(group, "beatlooproll_activate"); + } + } else { + if (engine.getValue(group, "loop_enabled") === 0) { + script.triggerControl(group, "reloop_toggle"); + } else { + script.triggerControl(group, "reloop_andstop"); + } + } + }, + shiftControl: true, + sendShifted: true, + shiftOffset: 0x01 + }); + + this.loopHalf = new components.Button({ + midi: [0x94 + channel, 0x34], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x02, + shift: function() { + this.disconnect(); + this.inKey = "loop_in"; + this.outKey = "loop_in"; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); + this.inKey = "loop_halve"; + this.outKey = "loop_halve"; + this.connect(); + this.trigger(); + } + }); + + this.loopDouble = new components.Button({ + midi: [0x94 + channel, 0x35], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x02, + shift: function() { + this.disconnect(); + this.inKey = "loop_out"; + this.outKey = "loop_out"; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); + this.inKey = "loop_double"; + this.outKey = "loop_double"; + this.connect(); + this.trigger(); + } + }); + + this.scratchToggle = new components.Button({ + // disconnects/connects are needed for the following scenario: + // 1. scratch mode is enabled (light on) + // 2. shift down + // 3. scratch button down + // 4. shift up + // 5. scratch button up + // scratch mode light is now off, should be on + key: "reverseroll", + midi: [0x90 + channel, 0x07], + shift: function() { + this.input = components.Button.prototype.input; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); // disconnect reverseroll light + this.input = function(channel, control, value) { + if (!this.isPress(channel, control, value)) { + return; + } + deck.scratchModeEnabled = !deck.scratchModeEnabled; + + // change the scratch mode status light + this.send(deck.scratchModeEnabled ? this.on : this.off); + }; + + // set current scratch mode status light + this.send(deck.scratchModeEnabled ? this.on : this.off); + }, + shiftControl: true, + sendShifted: true, + shiftOffset: 0x01 + }); + + this.pitchBendUp = new components.Button({ + shiftControl: true, + shiftOffset: 0x20, + shift: function() { + this.type = components.Button.prototype.types.toggle; + this.inKey = "keylock"; + }, + unshift: function() { + this.type = components.Button.prototype.types.push; + this.inKey = "rate_temp_up"; + } + }); + + this.pitchBendDown = new components.Button({ + currentRangeIdx: 0, + shift: function() { + this.input = function(channel, control, value) { + if (!this.isPress(channel, control, value)) { + return; + } + this.currentRangeIdx = (this.currentRangeIdx + 1) % MixtrackProFX.pitchRanges.length; + engine.setValue(this.group, "rateRange", MixtrackProFX.pitchRanges[this.currentRangeIdx]); + }; + }, + unshift: function() { + this.inKey = "rate_temp_down"; + this.input = components.Button.prototype.input; + } + }); + + this.setBeatgrid = new components.Button({ + key: "beats_translate_curpos", + midi: [0x98 + channel, 0x01 + (channel * 3)] + }); + + this.reconnectComponents(function(component) { + if (component.group === undefined) { + component.group = this.currentDeck; + } + }); +}; + +MixtrackProFX.Deck.prototype = new components.Deck(); + +MixtrackProFX.PadSection = function(deckNumber) { + components.ComponentContainer.call(this); + + this.blinkTimer = 0; + this.blinkLedState = true; + + // initialize leds + var ledOff = components.Button.prototype.off; + var ledOn = components.Button.prototype.on; + midi.sendShortMsg(0x93 + deckNumber, 0x00, ledOn); // hotcue + midi.sendShortMsg(0x93 + deckNumber, 0x0D, ledOff); // auto loop + midi.sendShortMsg(0x93 + deckNumber, 0x07, ledOff); // "fader cuts" + midi.sendShortMsg(0x93 + deckNumber, 0x0B, ledOff); // sample1 + + // shifted leds + midi.sendShortMsg(0x93 + deckNumber, 0x0F, ledOff); // sample2 + midi.sendShortMsg(0x93 + deckNumber, 0x02, ledOff); // beatjump + + this.modes = {}; + this.modes[MixtrackProFX.PadModeControls.HOTCUE] = new MixtrackProFX.ModeHotcue(deckNumber); + this.modes[MixtrackProFX.PadModeControls.AUTOLOOP] = new MixtrackProFX.ModeAutoLoop(deckNumber); + this.modes[MixtrackProFX.PadModeControls.FADERCUTS] = new MixtrackProFX.ModeFaderCuts(); + this.modes[MixtrackProFX.PadModeControls.SAMPLE1] = new MixtrackProFX.ModeSample(deckNumber, false); + this.modes[MixtrackProFX.PadModeControls.BEATJUMP] = new MixtrackProFX.ModeBeatjump(deckNumber); + this.modes[MixtrackProFX.PadModeControls.SAMPLE2] = new MixtrackProFX.ModeSample(deckNumber, true); + + this.modeButtonPress = function(channel, control, value) { + if (value !== 0x7F) { + return; + } + this.setMode(channel, control); + }; + + this.padPress = function(channel, control, value, status, group) { + if (this.currentMode.control === MixtrackProFX.PadModeControls.FADERCUTS) { + // don't activate pads when in "fader cuts" mode - handled by hardware of firmware + return; + } + var i = (control - 0x14) % 8; + this.currentMode.pads[i].input(channel, control, value, status, group); + }; + + this.setMode = function(channel, control) { + var newMode = this.modes[control]; + if (this.currentMode.control === newMode.control) { + return; // selected mode already set, no need to change anything + } + + this.currentMode.forEachComponent(function(component) { + component.disconnect(); + }); + + // set the correct shift state for new mode + if (this.isShifted) { + newMode.shift(); + } else { + newMode.unshift(); + } + + newMode.forEachComponent(function(component) { + component.connect(); + component.trigger(); + }); + + if (MixtrackProFX.enableBlink) { + // stop blinking if old mode was secondary mode + if (this.currentMode.secondaryMode) { + this.blinkLedOff(); + + // disable light on the old control in case it ended up in 0x7F state + midi.sendShortMsg(0x90 + channel, this.currentMode.unshiftedControl, 0x01); + } + + // start blinking if new mode is a secondary mode + if (newMode.secondaryMode) { + this.blinkLedOn(0x90 + channel, newMode.unshiftedControl); + } + } + + // light off on old mode select button + midi.sendShortMsg(0x90 + channel, this.currentMode.control, 0x01); + + // light on on new mode select button + midi.sendShortMsg(0x90 + channel, newMode.control, newMode.lightOnValue); + + if (newMode.control === MixtrackProFX.PadModeControls.FADERCUTS) { + // in "fader cuts" mode pad lights need to be disabled manually, + // as pads are controlled by hardware or firmware in this mode + // and don't have associated controls. without this, lights from + // previously selected mode would still be on after changing mode + // to "fader cuts" + this.disablePadLights(); + } + + this.currentMode = newMode; + }; + + // start an infinite timer that toggles led state + this.blinkLedOn = function(midi1, midi2) { + this.blinkLedOff(); + this.blinkLedState = true; + this.blinkTimer = engine.beginTimer(MixtrackProFX.blinkDelay, function() { + midi.sendShortMsg(midi1, midi2, this.blinkLedState ? 0x7F : 0x01); + this.blinkLedState = !this.blinkLedState; + }); + }; + + // stop the blink timer + this.blinkLedOff = function() { + if (this.blinkTimer === 0) { + return; + } + + engine.stopTimer(this.blinkTimer); + this.blinkTimer = 0; + }; + + this.disablePadLights = function() { + for (var i = 0; i < 16; i++) { // 0-7 = unshifted; 8-15 = shifted + midi.sendShortMsg(0x93 + deckNumber, 0x14 + i, 0x01); + } + }; + + this.currentMode = this.modes[MixtrackProFX.PadModeControls.HOTCUE]; +}; +MixtrackProFX.PadSection.prototype = Object.create(components.ComponentContainer.prototype); + +MixtrackProFX.ModeHotcue = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = MixtrackProFX.PadModeControls.HOTCUE; + this.secondaryMode = false; + this.lightOnValue = 0x7F; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 8; i++) { + this.pads[i] = new components.HotcueButton({ + group: "[Channel" + deckNumber + "]", + midi: [0x93 + deckNumber, 0x14 + i], + number: i + 1, + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + outConnect: false + }); + } +}; +MixtrackProFX.ModeHotcue.prototype = Object.create(components.ComponentContainer.prototype); + +MixtrackProFX.ModeAutoLoop = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = MixtrackProFX.PadModeControls.AUTOLOOP; + this.secondaryMode = false; + this.lightOnValue = 0x7F; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 8; i++) { + this.pads[i] = new components.Button({ + group: "[Channel" + deckNumber + "]", + midi: [0x93 + deckNumber, 0x14 + i], + size: MixtrackProFX.autoLoopSizes[i], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + shift: function() { + this.inKey = "beatlooproll_" + this.size + "_activate"; + this.outKey = "beatlooproll_" + this.size + "_activate"; + }, + unshift: function() { + this.inKey = "beatloop_" + this.size + "_toggle"; + this.outKey = "beatloop_" + this.size + "_enabled"; + }, + outConnect: false + }); + } +}; +MixtrackProFX.ModeAutoLoop.prototype = Object.create(components.ComponentContainer.prototype); + +// when pads are in "fader cuts" mode, they rapidly move the crossfader. +// holding a pad activates a "fader cut", releasing it causes the GUI crossfader +// to return to the position of physical crossfader +MixtrackProFX.ModeFaderCuts = function() { + components.ComponentContainer.call(this); + + this.control = MixtrackProFX.PadModeControls.FADERCUTS; + this.secondaryMode = false; + this.lightOnValue = 0x09; // for "fader cuts" 0x09 works better than 0x7F for some reason + + // pads are controlled by hardware of firmware in this mode + // pad input function is not called when pressing a pad in this mode +}; +MixtrackProFX.ModeFaderCuts.prototype = Object.create(components.ComponentContainer.prototype); + +MixtrackProFX.ModeSample = function(deckNumber, secondaryMode) { + components.ComponentContainer.call(this); + + if (!secondaryMode) { + // samples 1-8 + this.control = MixtrackProFX.PadModeControls.SAMPLE1; + this.firstSampleNumber = 1; + } else { + // samples 9-16 + this.control = MixtrackProFX.PadModeControls.SAMPLE2; + this.unshiftedControl = MixtrackProFX.PadModeControls.SAMPLE1; + this.firstSampleNumber = 9; + } + this.secondaryMode = secondaryMode; + this.lightOnValue = 0x7F; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 8; i++) { + this.pads[i] = new components.SamplerButton({ + midi: [0x93 + deckNumber, 0x14 + i], + number: this.firstSampleNumber + i, + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + outConnect: false + }); + } +}; +MixtrackProFX.ModeSample.prototype = Object.create(components.ComponentContainer.prototype); + +MixtrackProFX.ModeBeatjump = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = MixtrackProFX.PadModeControls.BEATJUMP; + this.secondaryMode = true; + this.unshiftedControl = MixtrackProFX.PadModeControls.HOTCUE; + this.lightOnValue = 0x7F; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 8; i++) { + this.pads[i] = new components.Button({ + group: "[Channel" + deckNumber + "]", + midi: [0x93 + deckNumber, 0x14 + i], + size: MixtrackProFX.beatJumpValues[i], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + shift: function() { + this.disconnect(); + this.inKey = "beatjump_" + this.size + "backward"; + this.outKey = "beatjump_" + this.size + "backward"; + this.connect(); + this.trigger(); + }, + unshift: function() { + this.disconnect(); + this.inKey = "beatjump_" + this.size + "forward"; + this.outKey = "beatjump_" + this.size + "forward"; + this.connect(); + this.trigger(); + }, + outConnect: false + }); + } +}; +MixtrackProFX.ModeBeatjump.prototype = Object.create(components.ComponentContainer.prototype); + +MixtrackProFX.Browse = function() { + this.knob = new components.Encoder({ + shiftControl: true, + shiftOffset: 0x01, + input: function(channel, control, value) { + var direction; + if (!MixtrackProFX.shifted) { + direction = (value > 0x40) ? value - 0x80 : value; + engine.setParameter("[Library]", "MoveVertical", direction); + } else { + direction = (value > 0x40) ? "up" : "down"; + engine.setParameter("[Channel1]", "waveform_zoom_" + direction, 1); + + // need to zoom both channels if waveform sync is disabled in Mixxx settings. + // and when it's enabled then no need to zoom 2nd channel, as it will cause + // the zoom to jump 2 levels at once + if (!MixtrackProFX.waveformsSynced) { + engine.setParameter("[Channel2]", "waveform_zoom_" + direction, 1); + } + } + } + }); + + this.knobButton = new components.Button({ + group: "[Library]", + shiftControl: true, + shiftOffset: 0x01, + shift: function() { + this.inKey = "GoToItem"; + }, + unshift: function() { + this.inKey = "MoveFocusForward"; + } + }); +}; +MixtrackProFX.Browse.prototype = new components.ComponentContainer(); + +MixtrackProFX.Gains = function() { + this.mainGain = new components.Pot({ + group: "[Master]", + inKey: "gain" + }); + + this.cueGain = new components.Pot({ + group: "[Master]", + inKey: "headGain" + }); + + this.cueMix = new components.Pot({ + group: "[Master]", + inKey: "headMix" + }); +}; +MixtrackProFX.Gains.prototype = new components.ComponentContainer(); + +MixtrackProFX.vuCallback = function(value, group) { + var level = value * 90; + var deckOffset = script.deckFromGroup(group) - 1; + midi.sendShortMsg(0xB0 + deckOffset, 0x1F, level); +}; + +MixtrackProFX.wheelTouch = function(channel, control, value) { + var deckNumber = channel + 1; + + if (!MixtrackProFX.shifted && MixtrackProFX.deck[channel].scratchModeEnabled && value === 0x7F) { + // touch start + + engine.scratchEnable(deckNumber, MixtrackProFX.jogScratchSensitivity, 33+1/3, MixtrackProFX.jogScratchAlpha, MixtrackProFX.jogScratchBeta, true); + } else if (value === 0) { + // touch end + engine.scratchDisable(deckNumber, true); + } +}; + +MixtrackProFX.wheelTurn = function(channel, control, value, status, group) { + var deckNumber = channel + 1; + + var newValue = value; + + if (value >= 64) { + // correct the value if going backwards + newValue -= 128; + } + + if (MixtrackProFX.shifted) { + // seek + var oldPos = engine.getValue(group, "playposition"); + + engine.setValue(group, "playposition", oldPos + newValue / MixtrackProFX.jogSeekSensitivity); + } else if (MixtrackProFX.deck[channel].scratchModeEnabled && engine.isScratching(deckNumber)) { + // scratch + engine.scratchTick(deckNumber, newValue); + } else { + // pitch bend + engine.setValue(group, "jog", newValue / MixtrackProFX.jogPitchSensitivity); + } +};