From ad6de8bc3fab92e0a5ba1c84f83f92b0cf9dc4b4 Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Thu, 30 Jun 2022 21:28:09 +1000 Subject: [PATCH 01/30] Numark Scratch: add initial mapping --- res/controllers/Numark Scratch.midi.xml | 977 ++++++++++++++++++++++ res/controllers/Numark-Scratch-scripts.js | 460 ++++++++++ 2 files changed, 1437 insertions(+) create mode 100644 res/controllers/Numark Scratch.midi.xml create mode 100644 res/controllers/Numark-Scratch-scripts.js diff --git a/res/controllers/Numark Scratch.midi.xml b/res/controllers/Numark Scratch.midi.xml new file mode 100644 index 000000000000..4d7808110de9 --- /dev/null +++ b/res/controllers/Numark Scratch.midi.xml @@ -0,0 +1,977 @@ + + + + Numark Scratch + Al Hadebe(NotYourAverageAl) + Mapping for the Numark Scratch Mixer + NumarkScratch + NumarkScratch + + + + + + + + + + + [Master] + NumarkScratch.setChannelInput + CH 1 PC + 0x8F + 0x57 + + + + + + [Master] + NumarkScratch.setChannelInput + CH 1 LINE/PHONO + 0x9F + 0x57 + + + + + + + [Master] + NumarkScratch.setChannelInput + CH 2 PC + 0x8F + 0x60 + + + + + + [Master] + NumarkScratch.setChannelInput + CH 2 LINE/PHONO + 0x9F + 0x60 + + + + + + + [Master] + NumarkScratch.crossfader.input + 0xBF + 0x08 + + + + + + + [Master] + NumarkScratch.gains.cueMix.input + 0xBF + 0x0D + + + + + + + [Channel1] + NumarkScratch.deck[0].gain.input + 0xB0 + 0x16 + + + + + + [Channel2] + NumarkScratch.deck[1].gain.input + 0xB1 + 0x16 + + + + + + + [EqualizerRack1_[Channel1]] + NumarkScratch.deck[0].treble.input + 0xB0 + 0x17 + + + + + + [EqualizerRack1_[Channel2]] + NumarkScratch.deck[1].treble.input + 0xB1 + 0x17 + + + + + + [EqualizerRack1_[Channel1]] + NumarkScratch.deck[0].mid.input + 0xB0 + 0x18 + + + + + + [EqualizerRack1_[Channel2]] + NumarkScratch.deck[1].mid.input + 0xB1 + 0x18 + + + + + + [EqualizerRack1_[Channel1]] + NumarkScratch.deck[0].bass.input + 0xB0 + 0x19 + + + + + + [EqualizerRack1_[Channel2]] + NumarkScratch.deck[1].bass.input + 0xB1 + 0x19 + + + + + + + [QuickEffectRack1_[Channel1]] + NumarkScratch.deck[0].filter.input + 0xB0 + 0x1A + + + + + + [QuickEffectRack1_[Channel2]] + NumarkScratch.deck[1].filter.input + 0xB1 + 0x1A + + + + + + + [Channel1] + NumarkScratch.deck[0].volume.input + 0xB0 + 0x1C + + + + + + [Channel2] + NumarkScratch.deck[1].volume.input + 0xB1 + 0x1C + + + + + + + [Mixer Profile] + NumarkScratch.crossfader.xFaderReverse + 0x9F + 0x1E + + + + + + + [Mixer Profile] + NumarkScratch.crossfader.xFaderReverse + 0x8F + 0x1E + + + + + + + [Mixer Profile] + NumarkScratch.crossfader.setCurve + 0xBF + 0x09 + + + + + + + [Channel1] + NumarkScratch.deck[0].shiftButton.input + 0x9F + 0x32 + + + + + + [Channel2] + NumarkScratch.deck[1].shiftButton.input + 0x9F + 0x32 + + + + + + + [Channel1] + NumarkScratch.deck[0].shiftButton.input + 0x8F + 0x32 + + + + + + [Channel2] + NumarkScratch.deck[1].shiftButton.input + 0x8F + 0x32 + + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x94 + 0x00 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x95 + 0x00 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x94 + 0x07 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x95 + 0x07 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x94 + 0x0B + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x95 + 0x0B + + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x84 + 0x00 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x85 + 0x00 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x84 + 0x07 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x85 + 0x07 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.modeButtonPress + 0x84 + 0x0B + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.modeButtonPress + 0x85 + 0x0B + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x14 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x14 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x15 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x15 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x16 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x16 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x17 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x17 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x14 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x14 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x15 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x15 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x16 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x16 + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x17 + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x17 + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x1C + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x1C + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x1D + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x1D + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x1E + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x1E + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x94 + 0x1F + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x95 + 0x1F + + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x1C + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x1C + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x1D + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x1D + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x1E + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x1E + + + + + + [Channel1] + NumarkScratch.deck[0].padSection.padPress + 0x84 + 0x1F + + + + + + [Channel2] + NumarkScratch.deck[1].padSection.padPress + 0x85 + 0x1F + + + + + + + [Channel1] + NumarkScratch.deck[0].loopEncoder.input + 0x94 + 0x34 + + + + + + [Channel1] + NumarkScratch.deck[0].loopEncoder.input + 0x94 + 0x35 + + + + + + [Channel2] + NumarkScratch.deck[1].loopEncoder.input + 0x95 + 0x34 + + + + + + [Channel2] + NumarkScratch.deck[1].loopEncoder.input + 0x95 + 0x35 + + + + + + + + [Channel1] + NumarkScratch.deck[0].loopEncoderButton.input + 0x94 + 0x3F + + + + + + [Channel2] + NumarkScratch.deck[1].loopEncoderButton.input + 0x95 + 0x3F + + + + + + + [Channel1] + NumarkScratch.deck[0].loopEncoderButton.input + 0x84 + 0x3F + + + + + + [Channel2] + NumarkScratch.deck[1].loopEncoderButton.input + 0x85 + 0x3F + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].dryWetKnob.input + 0xB8 + 0x04 + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].dryWetKnob.input + 0xB9 + 0x04 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect1 + 0x98 + 0x00 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect1 + 0x88 + 0x00 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect2 + 0x98 + 0x01 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect2 + 0x88 + 0x01 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect3 + 0x98 + 0x02 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].effect3 + 0x88 + 0x02 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect1 + 0x99 + 0x03 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect1 + 0x89 + 0x03 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect2 + 0x99 + 0x04 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect2 + 0x89 + 0x04 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect3 + 0x99 + 0x05 + + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].effect3 + 0x89 + 0x05 + + + + + + + [EffectRack1_EffectUnit1] + NumarkScratch.effect[0].enableSwitch + 0xB8 + 0x03 + + + + + + [EffectRack1_EffectUnit2] + NumarkScratch.effect[1].enableSwitch + 0xB9 + 0x03 + + + + + + + [Channel1] + NumarkScratch.deck[0].pflButton.input + 0x90 + 0x1B + + + + + + [Channel2] + NumarkScratch.deck[1].pflButton.input + 0x91 + 0x1B + + + + + + + [Channel1] + NumarkScratch.deck[0].pflButton.input + 0x80 + 0x1B + + + + + + [Channel2] + NumarkScratch.deck[1].pflButton.input + 0x81 + 0x1B + + + + + + + \ No newline at end of file diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js new file mode 100644 index 000000000000..26d2155da01a --- /dev/null +++ b/res/controllers/Numark-Scratch-scripts.js @@ -0,0 +1,460 @@ +var NumarkScratch = {}; + +///////////////// +// Tweakables. // +///////////////// + +// Beatloop Roll sizes for the 4 pads, for available values see: +// https://manual.mixxx.org/2.3/en/chapters/appendix/mixxx_controls.html#control-[ChannelN]-beatloop_X_toggle +NumarkScratch.autoLoopSizes = [ + "0.25", + "0.5", + "1", + "2", +]; + +// Default is false. When set to false, the EncoderKnob manages looping. Shift + EncoderKnob scrolls the library/loads track +// If set to true, the EncoderKnob scrolls the library/loads track. Shift + EncoderKnob manages looping. +NumarkScratch.invertLoopEncoderFunction = false; + +// Turn off all when inactive instead default is 0x00 (Off) +// Set to 0x01 is you want lights to be dim +NumarkScratch.LOW_LIGHT = 0x00; + +/////////// +// Code. // +/////////// + +// State variable, don't touch +NumarkScratch.shifted = false; + +components.Button.prototype.off = NumarkScratch.LOW_LIGHT + +NumarkScratch.init = function() { + // Initialize component containers + NumarkScratch.deck = new components.ComponentContainer(); + NumarkScratch.effect = new components.ComponentContainer(); + for (var i = 0; i < 2; i++) { + NumarkScratch.deck[i] = new NumarkScratch.Deck(i + 1); + NumarkScratch.effect[i] = new NumarkScratch.EffectUnit(i + 1); + } + + NumarkScratch.gains = new NumarkScratch.Gains(); + + //Toggle the vinyl control section in skins to show + engine.setValue("[VinylControl]", "show_vinylcontrol", 1); + + // Send Serato SysEx messages to request initial state and unlock pads + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7], 6); + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x01, 0xF7], 6); + + engine.makeConnection("[Channel1]", "VuMeter", NumarkScratch.vuCallback); + engine.makeConnection("[Channel2]", "VuMeter", NumarkScratch.vuCallback); + + // Trigger is needed to initialize lights to 0x01 + NumarkScratch.deck.forEachComponent(function(component) { + component.trigger(); + }); + NumarkScratch.effect.forEachComponent(function(component) { + component.trigger(); + }); + + // set FX buttons init light & Shift button init light + midi.sendShortMsg(0x98, 0x00, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x98, 0x01, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x98, 0x02, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x03, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x04, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x05, NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x9F, 0x32, NumarkScratch.LOW_LIGHT); +}; + +NumarkScratch.shutdown = function() { + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x04, 0xF7], 6); +}; + +NumarkScratch.shift = function() { + NumarkScratch.shifted = true; + NumarkScratch.deck.shift(); + NumarkScratch.effect.shift(); +}; + +NumarkScratch.unshift = function() { + NumarkScratch.shifted = false; + NumarkScratch.deck.unshift(); + NumarkScratch.effect.unshift(); +}; + +NumarkScratch.allEffectOff = function() { + NumarkScratch.effect[0].effects=[false, false, false]; + NumarkScratch.effect[1].effects=[false, false, false]; + NumarkScratch.FxUpdateLEDs(); + NumarkScratch.effect[0].updateEffects(); + NumarkScratch.effect[1].updateEffects(); +}; + +NumarkScratch.FxUpdateLEDs = function() { + var newStates1=[false, false, false]; + var newStates2=[false, false, false]; + newStates1=NumarkScratch.effect[0].effects; + newStates2=NumarkScratch.effect[1].effects; + midi.sendShortMsg(0x98, 0x00, newStates1[0] ? 0x7F:NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x98, 0x01, newStates1[1] ? 0x7F:NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x98, 0x02, newStates1[2] ? 0x7F:NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x03, newStates2[0] ? 0x7F:NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x04, newStates2[1] ? 0x7F:NumarkScratch.LOW_LIGHT); + midi.sendShortMsg(0x99, 0x05, newStates2[2] ? 0x7F:NumarkScratch.LOW_LIGHT); +}; +// 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) +NumarkScratch.EffectUnit = function(deckNumber) { + this.effects = [false, false, false]; + this.isSwitchHoldOn = false; + + this.updateEffects = function() { + for (var i = 1; i <= this.effects.length; i++) { + engine.setValue("[EffectRack1_EffectUnit" + deckNumber + "_Effect"+i+"]", "enabled", this.effects[i-1]); + } + } + + // switch values are: + // 0 - switch in the middle + // 1 - switch up + // 2 - switch down + this.enableSwitch = function(channel, control, value, status, group) { + this.isSwitchHoldOn = value != 0; + engine.setValue("[EffectRack1_EffectUnit1]", "super1", Math.min(value, 1.0)); + engine.setValue("[EffectRack1_EffectUnit2]", "super1", Math.min(value, 1.0)); + engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", (value != 0)); + engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", (value != 0)); + this.updateEffects(); + } + + this.dryWetKnob = new components.Pot({ + group: "[EffectRack1_EffectUnit" + deckNumber + "]", + inKey: "mix" + }); + + this.effect1 = function(channel, control, value, status, group) { + if (value == 0x7F) { + if (!NumarkScratch.shifted) + { + NumarkScratch.allEffectOff(); + } + this.effects[0] = !this.effects[0]; + midi.sendShortMsg(status, control, this.effects[0] ? 0x7F : NumarkScratch.LOW_LIGHT); + } + + this.updateEffects(); + } + + this.effect2 = function(channel, control, value, status, group) { + if (value == 0x7F) { + if (!NumarkScratch.shifted) + { + NumarkScratch.allEffectOff(); + } + this.effects[1] = !this.effects[1]; + midi.sendShortMsg(status, control, this.effects[1] ? 0x7F : NumarkScratch.LOW_LIGHT); + } + + this.updateEffects(); + } + + this.effect3 = function(channel, control, value, status, group) { + if (value == 0x7F) { + if (!NumarkScratch.shifted) + { + NumarkScratch.allEffectOff(); + } + this.effects[2] = !this.effects[2]; + midi.sendShortMsg(status, control, this.effects[2] ? 0x7F : NumarkScratch.LOW_LIGHT); + } + this.updateEffects(); + } +}; +NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); + +NumarkScratch.crossfader = new components.Pot({ + midi: [0xBF, 0x08], + group: "[Master]", + inKey: "crossfader", +}); + +NumarkScratch.crossfader.setCurve = function(channel, control, value, _status, _group) { + switch (value) { + case 0x00: // Additive/Linear + engine.setValue("[Mixer Profile]", "xFaderMode", 0); + engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.4); + engine.setValue("[Mixer Profile]", "xFaderCurve", 0.9); + break; + case 0x7F: // Picnic Bench/Fast Cut + engine.setValue("[Mixer Profile]", "xFaderMode", 0); + engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.9); + engine.setValue("[Mixer Profile]", "xFaderCurve", 7.0); + } +}; + +NumarkScratch.crossfader.xFaderReverse = function(channel, control, value, _status, _group) { + // 0x7F is ON, 0x00 is OFF + engine.setValue("[Mixer Profile]", "xFaderReverse", (value === 0x7F) ? 1 : 0); +}; + +NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { + const number = (control === 0x57) ? 1 : 2; + const channelgroup = "[Channel" + number + "]"; + + switch (value) { + case 0x00: // PC and turn on vinyl control + engine.setValue(channelgroup, "passthrough", 0); + engine.setValue(channelgroup, "vinylcontrol_enabled", 1); + break; + case 0x02: // PHONO/LINE and turn off vinyl control + engine.setValue(channelgroup, "passthrough", 1); + engine.setValue(channelgroup, "vinylcontrol_enabled", 0); + break; + } +}; + +NumarkScratch.Deck = function(number) { + components.Deck.call(this, number); + + var channel = number - 1; + var deck = this; + + this.pflButton = new components.Button({ + midi: [0x90 + channel, 0x1B], + key: "pfl", + output: function(value) { + var note = (value === 0x00 ? 0x80 : 0x90) + channel; + midi.sendShortMsg(note, 0x1B, this.outValueScale(value)); + } + }); + + 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.loopEncoder = new components.Encoder({ + unshift: function() { + if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function + this.input = function(channel, control, value, status, group) { + var loopSize = engine.getValue(this.group, "beatloop_size"); + if (control == 52 && loopSize >= (1/16)) { //turn left + engine.setValue(this.group, "beatloop_size", loopSize / 2); + } else if (control == 53 && loopSize < 256) { // turn right + engine.setValue(this.group, "beatloop_size", loopSize * 2); + } + }; + } + else { + this.input = function(channel, control, value, status, group) { // if set to true invert function + var direction = (control == 52) ? "Down" : "Up"; //turn left: turn right + script.triggerControl("[Library]", "Move" + direction); + }; + } + }, + shift: function() { + if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function + this.input = function(channel, control, value, status, group) { + var direction = (control == 52) ? "Down" : "Up"; //turn left: turn right + script.triggerControl("[Library]", "Move" + direction); + }; + } + else { + this.input = function(channel, control, value, status, group) { // if set to true invert function + var loopSize = engine.getValue(this.group, "beatloop_size"); + if (control == 52 && loopSize >= (1/16)) { //turn left + engine.setValue(this.group, "beatloop_size", loopSize / 2); + } else if (control == 53 && loopSize < 256) { //turn right + engine.setValue(this.group, "beatloop_size", loopSize * 2); + } + }; + } + }, + }); + + this.loopEncoderButton = new components.Button({ + shift: function() { + if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function + this.inKey = "LoadSelectedTrack"; + } + else { + this.inKey = "beatloop_activate"; // if set to true invert function + } + }, + unshift: function() { + if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function + this.inKey = "beatloop_activate"; + } + + else { + this.inKey = "LoadSelectedTrack"; // if set to true invert function + } + } + }); + + this.padSection = new NumarkScratch.PadSection(number); + + this.shiftButton = new components.Button({ + input: function(channel, control, value) { + if (this.isPress(channel, control, value)) { + NumarkScratch.shift(); + midi.sendShortMsg(0x9F, 0x32, 0x7F); + } else { + NumarkScratch.unshift(); + midi.sendShortMsg(0x9F, 0x32, NumarkScratch.LOW_LIGHT); + } + } + }); + + this.reconnectComponents(function(component) { + if (component.group === undefined) { + component.group = this.currentDeck; + } + }); +}; + +NumarkScratch.Deck.prototype = new components.Deck(); + +// Pad modes control codes +NumarkScratch.PadModeControls = { + HOTCUE: 0x00, + SAMPLER: 0x07, + ROLL: 0x0B, +}; + +NumarkScratch.PadSection = function(deckNumber) { + components.ComponentContainer.call(this); + + this.modes = {}; + this.modes[NumarkScratch.PadModeControls.HOTCUE] = new NumarkScratch.ModeHotcue(deckNumber); + this.modes[NumarkScratch.PadModeControls.SAMPLER] = new NumarkScratch.ModeSampler(deckNumber); + this.modes[NumarkScratch.PadModeControls.ROLL] = new NumarkScratch.ModeRoll(deckNumber); + + this.modeButtonPress = function(channel, control, _value) { + this.setMode(channel, control); + }; + + this.padPress = function(channel, control, value, status, group) { + 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]; + this.currentMode.forEachComponent(function(component) { + component.disconnect(); + }); + + newMode.forEachComponent(function(component) { + component.connect(); + component.trigger(); + }); + + this.currentMode = newMode; + }; + + this.currentMode = this.modes[NumarkScratch.PadModeControls.HOTCUE]; +}; +NumarkScratch.PadSection.prototype = Object.create(components.ComponentContainer.prototype); + +NumarkScratch.ModeHotcue = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = NumarkScratch.PadModeControls.HOTCUE; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 4; 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 + }); + } +}; +NumarkScratch.ModeHotcue.prototype = Object.create(components.ComponentContainer.prototype); + +NumarkScratch.ModeRoll = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = NumarkScratch.PadModeControls.ROLL; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 4; i++) { + this.pads[i] = new components.Button({ + group: "[Channel" + deckNumber + "]", + midi: [0x93 + deckNumber, 0x14 + i], + size: NumarkScratch.autoLoopSizes[i], + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + inKey: "beatlooproll_" + NumarkScratch.autoLoopSizes[i] + "_activate", + outKey: "beatloop_" + NumarkScratch.autoLoopSizes[i] + "_enabled", + outConnect: false + }); + } +}; +NumarkScratch.ModeRoll.prototype = Object.create(components.ComponentContainer.prototype); + +NumarkScratch.ModeSampler = function(deckNumber) { + components.ComponentContainer.call(this); + + this.control = NumarkScratch.PadModeControls.SAMPLER; + + this.pads = new components.ComponentContainer(); + for (var i = 0; i < 4; i++) { + this.pads[i] = new components.SamplerButton({ + midi: [0x93 + deckNumber, 0x14 + i], + number: i + 1, + shiftControl: true, + sendShifted: true, + shiftOffset: 0x08, + outConnect: false + }); + } +}; +NumarkScratch.ModeSampler.prototype = Object.create(components.ComponentContainer.prototype); + +NumarkScratch.Gains = function() { + this.cueMix = new components.Pot({ + group: "[Master]", + inKey: "headMix" + }); +}; +NumarkScratch.Gains.prototype = new components.ComponentContainer(); + +NumarkScratch.vuCallback = function(value, group) { + var level = value * 90; + var deckOffset = script.deckFromGroup(group) - 1; + midi.sendShortMsg(0xB0 + deckOffset, 0x1F, level); +}; \ No newline at end of file From 71651119369fbe228ed12a6c902588d75a5ee384 Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Thu, 30 Jun 2022 23:08:54 +1000 Subject: [PATCH 02/30] pre-commit fixes --- res/controllers/Numark Scratch.midi.xml | 4 +- res/controllers/Numark-Scratch-scripts.js | 132 ++++++++++------------ 2 files changed, 64 insertions(+), 72 deletions(-) diff --git a/res/controllers/Numark Scratch.midi.xml b/res/controllers/Numark Scratch.midi.xml index 4d7808110de9..736334010fab 100644 --- a/res/controllers/Numark Scratch.midi.xml +++ b/res/controllers/Numark Scratch.midi.xml @@ -207,7 +207,7 @@ - + [Mixer Profile] @@ -974,4 +974,4 @@ - \ No newline at end of file + diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 26d2155da01a..49619cf6d055 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -28,7 +28,7 @@ NumarkScratch.LOW_LIGHT = 0x00; // State variable, don't touch NumarkScratch.shifted = false; -components.Button.prototype.off = NumarkScratch.LOW_LIGHT +components.Button.prototype.off = NumarkScratch.LOW_LIGHT; NumarkScratch.init = function() { // Initialize component containers @@ -57,7 +57,7 @@ NumarkScratch.init = function() { }); NumarkScratch.effect.forEachComponent(function(component) { component.trigger(); - }); + }); // set FX buttons init light & Shift button init light midi.sendShortMsg(0x98, 0x00, NumarkScratch.LOW_LIGHT); @@ -86,18 +86,18 @@ NumarkScratch.unshift = function() { }; NumarkScratch.allEffectOff = function() { - NumarkScratch.effect[0].effects=[false, false, false]; - NumarkScratch.effect[1].effects=[false, false, false]; + NumarkScratch.effect[0].effects=[false, false, false]; + NumarkScratch.effect[1].effects=[false, false, false]; NumarkScratch.FxUpdateLEDs(); - NumarkScratch.effect[0].updateEffects(); - NumarkScratch.effect[1].updateEffects(); + NumarkScratch.effect[0].updateEffects(); + NumarkScratch.effect[1].updateEffects(); }; NumarkScratch.FxUpdateLEDs = function() { - var newStates1=[false, false, false]; - var newStates2=[false, false, false]; - newStates1=NumarkScratch.effect[0].effects; - newStates2=NumarkScratch.effect[1].effects; + var newStates1=[false, false, false]; + var newStates2=[false, false, false]; + newStates1=NumarkScratch.effect[0].effects; + newStates2=NumarkScratch.effect[1].effects; midi.sendShortMsg(0x98, 0x00, newStates1[0] ? 0x7F:NumarkScratch.LOW_LIGHT); midi.sendShortMsg(0x98, 0x01, newStates1[1] ? 0x7F:NumarkScratch.LOW_LIGHT); midi.sendShortMsg(0x98, 0x02, newStates1[2] ? 0x7F:NumarkScratch.LOW_LIGHT); @@ -108,71 +108,68 @@ NumarkScratch.FxUpdateLEDs = function() { // 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) -NumarkScratch.EffectUnit = function(deckNumber) { +NumarkScratch.EffectUnit = function(deckNumber) { this.effects = [false, false, false]; this.isSwitchHoldOn = false; - + this.updateEffects = function() { - for (var i = 1; i <= this.effects.length; i++) { - engine.setValue("[EffectRack1_EffectUnit" + deckNumber + "_Effect"+i+"]", "enabled", this.effects[i-1]); + for (var i = 1; i <= this.effects.length; i++) { + engine.setValue("[EffectRack1_EffectUnit" + deckNumber + "_Effect"+i+"]", "enabled", this.effects[i-1]); } - } + }; // switch values are: // 0 - switch in the middle // 1 - switch up - // 2 - switch down - this.enableSwitch = function(channel, control, value, status, group) { - this.isSwitchHoldOn = value != 0; + // 2 - switch down + this.enableSwitch = function(channel, control, value, _status, _group) { + this.isSwitchHoldOn = value !== 0; engine.setValue("[EffectRack1_EffectUnit1]", "super1", Math.min(value, 1.0)); engine.setValue("[EffectRack1_EffectUnit2]", "super1", Math.min(value, 1.0)); - engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", (value != 0)); - engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", (value != 0)); + engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); + engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); this.updateEffects(); - } + }; this.dryWetKnob = new components.Pot({ group: "[EffectRack1_EffectUnit" + deckNumber + "]", inKey: "mix" }); - - this.effect1 = function(channel, control, value, status, group) { - if (value == 0x7F) { - if (!NumarkScratch.shifted) - { - NumarkScratch.allEffectOff(); - } + + this.effect1 = function(channel, control, value, status, _group) { + if (value === 0x7F) { + if (!NumarkScratch.shifted) { + NumarkScratch.allEffectOff(); + } this.effects[0] = !this.effects[0]; midi.sendShortMsg(status, control, this.effects[0] ? 0x7F : NumarkScratch.LOW_LIGHT); } - + this.updateEffects(); - } - - this.effect2 = function(channel, control, value, status, group) { - if (value == 0x7F) { - if (!NumarkScratch.shifted) - { - NumarkScratch.allEffectOff(); - } + }; + + this.effect2 = function(channel, control, value, status, _group) { + if (value === 0x7F) { + if (!NumarkScratch.shifted) { + NumarkScratch.allEffectOff(); + } this.effects[1] = !this.effects[1]; midi.sendShortMsg(status, control, this.effects[1] ? 0x7F : NumarkScratch.LOW_LIGHT); } this.updateEffects(); - } - - this.effect3 = function(channel, control, value, status, group) { - if (value == 0x7F) { - if (!NumarkScratch.shifted) - { - NumarkScratch.allEffectOff(); - } + }; + + this.effect3 = function(channel, control, value, status, _group) { + if (value === 0x7F) { + if (!NumarkScratch.shifted) { + NumarkScratch.allEffectOff(); + } this.effects[2] = !this.effects[2]; midi.sendShortMsg(status, control, this.effects[2] ? 0x7F : NumarkScratch.LOW_LIGHT); } this.updateEffects(); - } + }; }; NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); @@ -194,7 +191,7 @@ NumarkScratch.crossfader.setCurve = function(channel, control, value, _status, _ engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.9); engine.setValue("[Mixer Profile]", "xFaderCurve", 7.0); } -}; +}; NumarkScratch.crossfader.xFaderReverse = function(channel, control, value, _status, _group) { // 0x7F is ON, 0x00 is OFF @@ -202,8 +199,8 @@ NumarkScratch.crossfader.xFaderReverse = function(channel, control, value, _stat }; NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { - const number = (control === 0x57) ? 1 : 2; - const channelgroup = "[Channel" + number + "]"; + var number = (control === 0x57) ? 1 : 2; + var channelgroup = "[Channel" + number + "]"; switch (value) { case 0x00: // PC and turn on vinyl control @@ -221,7 +218,7 @@ NumarkScratch.Deck = function(number) { components.Deck.call(this, number); var channel = number - 1; - var deck = this; + //var deck = this; this.pflButton = new components.Button({ midi: [0x90 + channel, 0x1B], @@ -263,35 +260,33 @@ NumarkScratch.Deck = function(number) { this.loopEncoder = new components.Encoder({ unshift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.input = function(channel, control, value, status, group) { + this.input = function(channel, control, _value, _status, _group) { var loopSize = engine.getValue(this.group, "beatloop_size"); - if (control == 52 && loopSize >= (1/16)) { //turn left + if (control === 52 && loopSize >= (1/16)) { //turn left engine.setValue(this.group, "beatloop_size", loopSize / 2); - } else if (control == 53 && loopSize < 256) { // turn right + } else if (control === 53 && loopSize < 256) { // turn right engine.setValue(this.group, "beatloop_size", loopSize * 2); } }; - } - else { - this.input = function(channel, control, value, status, group) { // if set to true invert function - var direction = (control == 52) ? "Down" : "Up"; //turn left: turn right + } else { + this.input = function(channel, control, _value, _status, _group) { // if set to true invert function + var direction = (control === 52) ? "Down" : "Up"; //turn left: turn right script.triggerControl("[Library]", "Move" + direction); }; } }, shift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.input = function(channel, control, value, status, group) { - var direction = (control == 52) ? "Down" : "Up"; //turn left: turn right + this.input = function(channel, control, _value, _status, _group) { + var direction = (control === 52) ? "Down" : "Up"; //turn left: turn right script.triggerControl("[Library]", "Move" + direction); }; - } - else { - this.input = function(channel, control, value, status, group) { // if set to true invert function + } else { + this.input = function(channel, control, _value, _status, _group) { // if set to true invert function var loopSize = engine.getValue(this.group, "beatloop_size"); - if (control == 52 && loopSize >= (1/16)) { //turn left + if (control === 52 && loopSize >= (1/16)) { //turn left engine.setValue(this.group, "beatloop_size", loopSize / 2); - } else if (control == 53 && loopSize < 256) { //turn right + } else if (control === 53 && loopSize < 256) { //turn right engine.setValue(this.group, "beatloop_size", loopSize * 2); } }; @@ -303,17 +298,14 @@ NumarkScratch.Deck = function(number) { shift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function this.inKey = "LoadSelectedTrack"; - } - else { + } else { this.inKey = "beatloop_activate"; // if set to true invert function } }, unshift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function this.inKey = "beatloop_activate"; - } - - else { + } else { this.inKey = "LoadSelectedTrack"; // if set to true invert function } } @@ -457,4 +449,4 @@ NumarkScratch.vuCallback = function(value, group) { var level = value * 90; var deckOffset = script.deckFromGroup(group) - 1; midi.sendShortMsg(0xB0 + deckOffset, 0x1F, level); -}; \ No newline at end of file +}; From 2b2c83336d8ccd1c15c9519bfeb3613d813a50b8 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Tue, 5 Jul 2022 06:29:12 +1000 Subject: [PATCH 03/30] Update res/controllers/Numark-Scratch-scripts.js Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Numark-Scratch-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 49619cf6d055..f6b740bbb173 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -70,7 +70,7 @@ NumarkScratch.init = function() { }; NumarkScratch.shutdown = function() { - midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x04, 0xF7], 6); + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x04, 0xF7]); }; NumarkScratch.shift = function() { From 897d459558fed89d5e73a1b2f95e348aa9af1c5f Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Tue, 5 Jul 2022 06:31:39 +1000 Subject: [PATCH 04/30] Update res/controllers/Numark-Scratch-scripts.js Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Numark-Scratch-scripts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index f6b740bbb173..2cd0e9a608dd 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -315,12 +315,13 @@ NumarkScratch.Deck = function(number) { this.shiftButton = new components.Button({ input: function(channel, control, value) { + midi: [0x9F, 0x32], if (this.isPress(channel, control, value)) { NumarkScratch.shift(); - midi.sendShortMsg(0x9F, 0x32, 0x7F); + this.send(this.on); } else { NumarkScratch.unshift(); - midi.sendShortMsg(0x9F, 0x32, NumarkScratch.LOW_LIGHT); + this.send(this.off); } } }); From 0924bb56ae6095559aa1dcd69ad87fab8bfc1359 Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 18:41:53 +1000 Subject: [PATCH 05/30] remove extra sysex message --- res/controllers/Numark-Scratch-scripts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 2cd0e9a608dd..66397908ef1a 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -45,8 +45,7 @@ NumarkScratch.init = function() { engine.setValue("[VinylControl]", "show_vinylcontrol", 1); // Send Serato SysEx messages to request initial state and unlock pads - midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7], 6); - midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x01, 0xF7], 6); + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); engine.makeConnection("[Channel1]", "VuMeter", NumarkScratch.vuCallback); engine.makeConnection("[Channel2]", "VuMeter", NumarkScratch.vuCallback); @@ -314,8 +313,8 @@ NumarkScratch.Deck = function(number) { this.padSection = new NumarkScratch.PadSection(number); this.shiftButton = new components.Button({ + midi: [0x9F, 0x32], input: function(channel, control, value) { - midi: [0x9F, 0x32], if (this.isPress(channel, control, value)) { NumarkScratch.shift(); this.send(this.on); From c7176b845985285eca1cbb9159df36dce770922c Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 18:47:44 +1000 Subject: [PATCH 06/30] remove unnecessary "show vinyl control" --- res/controllers/Numark-Scratch-scripts.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 66397908ef1a..861310eb7e0d 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -41,9 +41,6 @@ NumarkScratch.init = function() { NumarkScratch.gains = new NumarkScratch.Gains(); - //Toggle the vinyl control section in skins to show - engine.setValue("[VinylControl]", "show_vinylcontrol", 1); - // Send Serato SysEx messages to request initial state and unlock pads midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); From 961e35f3ec970e444776b4e15af479588920fc0c Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 18:53:00 +1000 Subject: [PATCH 07/30] remove unnecessary gains componentContainer --- res/controllers/Numark-Scratch-scripts.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 861310eb7e0d..661bd1d6dc70 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -39,8 +39,6 @@ NumarkScratch.init = function() { NumarkScratch.effect[i] = new NumarkScratch.EffectUnit(i + 1); } - NumarkScratch.gains = new NumarkScratch.Gains(); - // Send Serato SysEx messages to request initial state and unlock pads midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); @@ -253,6 +251,11 @@ NumarkScratch.Deck = function(number) { inKey: "pregain" }); + this.cueMix = new components.Pot({ + group: "[Master]", + inKey: "headMix" + }); + this.loopEncoder = new components.Encoder({ unshift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function @@ -434,13 +437,6 @@ NumarkScratch.ModeSampler = function(deckNumber) { }; NumarkScratch.ModeSampler.prototype = Object.create(components.ComponentContainer.prototype); -NumarkScratch.Gains = function() { - this.cueMix = new components.Pot({ - group: "[Master]", - inKey: "headMix" - }); -}; -NumarkScratch.Gains.prototype = new components.ComponentContainer(); NumarkScratch.vuCallback = function(value, group) { var level = value * 90; From e129628d2e7688d9f77047e2db5d841b6600b6ab Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 20:12:22 +1000 Subject: [PATCH 08/30] vumeter function --- res/controllers/Numark-Scratch-scripts.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 661bd1d6dc70..274e8f66ed92 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -42,8 +42,14 @@ NumarkScratch.init = function() { // Send Serato SysEx messages to request initial state and unlock pads midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); - engine.makeConnection("[Channel1]", "VuMeter", NumarkScratch.vuCallback); - engine.makeConnection("[Channel2]", "VuMeter", NumarkScratch.vuCallback); + var createVuCallback = function(deckOffset) { + return function(value) { + midi.sendShortMsg(0xB0 + deckOffset, 0x1F, value * 90); + }; + }; + + engine.makeConnection("[Channel1]", "VuMeter", createVuCallback(0)); + engine.makeConnection("[Channel2]", "VuMeter", createVuCallback(1)); // Trigger is needed to initialize lights to 0x01 NumarkScratch.deck.forEachComponent(function(component) { @@ -436,10 +442,3 @@ NumarkScratch.ModeSampler = function(deckNumber) { } }; NumarkScratch.ModeSampler.prototype = Object.create(components.ComponentContainer.prototype); - - -NumarkScratch.vuCallback = function(value, group) { - var level = value * 90; - var deckOffset = script.deckFromGroup(group) - 1; - midi.sendShortMsg(0xB0 + deckOffset, 0x1F, level); -}; From 4d38fbe3d619ec0dc23de350e713edf66e2d36aa Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 20:15:43 +1000 Subject: [PATCH 09/30] cueMix midi file fix --- res/controllers/Numark Scratch.midi.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark Scratch.midi.xml b/res/controllers/Numark Scratch.midi.xml index 736334010fab..0c4a278a0e9c 100644 --- a/res/controllers/Numark Scratch.midi.xml +++ b/res/controllers/Numark Scratch.midi.xml @@ -69,7 +69,7 @@ [Master] - NumarkScratch.gains.cueMix.input + NumarkScratch.cueMix.input 0xBF 0x0D From 50ae823511a48f7990013a2c8e80a4ee9951b5f4 Mon Sep 17 00:00:00 2001 From: NotYourAverageAl Date: Tue, 5 Jul 2022 21:12:44 +1000 Subject: [PATCH 10/30] cueMix changed to normal headMix --- res/controllers/Numark Scratch.midi.xml | 4 ++-- res/controllers/Numark-Scratch-scripts.js | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/res/controllers/Numark Scratch.midi.xml b/res/controllers/Numark Scratch.midi.xml index 0c4a278a0e9c..b94b89876293 100644 --- a/res/controllers/Numark Scratch.midi.xml +++ b/res/controllers/Numark Scratch.midi.xml @@ -69,11 +69,11 @@ [Master] - NumarkScratch.cueMix.input + headMix 0xBF 0x0D - + diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 274e8f66ed92..cf9028ec194d 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -257,11 +257,6 @@ NumarkScratch.Deck = function(number) { inKey: "pregain" }); - this.cueMix = new components.Pot({ - group: "[Master]", - inKey: "headMix" - }); - this.loopEncoder = new components.Encoder({ unshift: function() { if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function From f2f5ed01e9a8aaf3517280d77145753e0469ab5d Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Fri, 17 Mar 2023 07:56:39 +1100 Subject: [PATCH 11/30] Rename Numark Scratch.midi.xml to Numark-Scratch.midi.xml --- .../{Numark Scratch.midi.xml => Numark-Scratch.midi.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename res/controllers/{Numark Scratch.midi.xml => Numark-Scratch.midi.xml} (100%) diff --git a/res/controllers/Numark Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml similarity index 100% rename from res/controllers/Numark Scratch.midi.xml rename to res/controllers/Numark-Scratch.midi.xml From 0b606a281386d203e0df6c342145491a7f81d15a Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Fri, 17 Mar 2023 21:57:18 +1100 Subject: [PATCH 12/30] update loop encoder & button to components --- res/controllers/Numark-Scratch-scripts.js | 126 ++++++++++------------ res/controllers/Numark-Scratch.midi.xml | 54 ++-------- 2 files changed, 67 insertions(+), 113 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index cf9028ec194d..750a4b0aa40d 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -34,7 +34,7 @@ NumarkScratch.init = function() { // Initialize component containers NumarkScratch.deck = new components.ComponentContainer(); NumarkScratch.effect = new components.ComponentContainer(); - for (var i = 0; i < 2; i++) { + for (let i = 0; i < 2; i++) { NumarkScratch.deck[i] = new NumarkScratch.Deck(i + 1); NumarkScratch.effect[i] = new NumarkScratch.EffectUnit(i + 1); } @@ -42,7 +42,7 @@ NumarkScratch.init = function() { // Send Serato SysEx messages to request initial state and unlock pads midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); - var createVuCallback = function(deckOffset) { + const createVuCallback = function(deckOffset) { return function(value) { midi.sendShortMsg(0xB0 + deckOffset, 0x1F, value * 90); }; @@ -94,8 +94,8 @@ NumarkScratch.allEffectOff = function() { }; NumarkScratch.FxUpdateLEDs = function() { - var newStates1=[false, false, false]; - var newStates2=[false, false, false]; + let newStates1=[false, false, false]; + let newStates2=[false, false, false]; newStates1=NumarkScratch.effect[0].effects; newStates2=NumarkScratch.effect[1].effects; midi.sendShortMsg(0x98, 0x00, newStates1[0] ? 0x7F:NumarkScratch.LOW_LIGHT); @@ -113,7 +113,7 @@ NumarkScratch.EffectUnit = function(deckNumber) { this.isSwitchHoldOn = false; this.updateEffects = function() { - for (var i = 1; i <= this.effects.length; i++) { + for (let i = 1; i <= this.effects.length; i++) { engine.setValue("[EffectRack1_EffectUnit" + deckNumber + "_Effect"+i+"]", "enabled", this.effects[i-1]); } }; @@ -199,8 +199,8 @@ NumarkScratch.crossfader.xFaderReverse = function(channel, control, value, _stat }; NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { - var number = (control === 0x57) ? 1 : 2; - var channelgroup = "[Channel" + number + "]"; + const number = (control === 0x57) ? 1 : 2; + const channelgroup = "[Channel" + number + "]"; switch (value) { case 0x00: // PC and turn on vinyl control @@ -217,14 +217,13 @@ NumarkScratch.setChannelInput = function(channel, control, value, _status, _grou NumarkScratch.Deck = function(number) { components.Deck.call(this, number); - var channel = number - 1; - //var deck = this; + const channel = number; this.pflButton = new components.Button({ midi: [0x90 + channel, 0x1B], key: "pfl", output: function(value) { - var note = (value === 0x00 ? 0x80 : 0x90) + channel; + const note = (value === 0x00 ? 0x80 : 0x90) + channel; midi.sendShortMsg(note, 0x1B, this.outValueScale(value)); } }); @@ -257,59 +256,52 @@ NumarkScratch.Deck = function(number) { inKey: "pregain" }); - this.loopEncoder = new components.Encoder({ - unshift: function() { - if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.input = function(channel, control, _value, _status, _group) { - var loopSize = engine.getValue(this.group, "beatloop_size"); - if (control === 52 && loopSize >= (1/16)) { //turn left - engine.setValue(this.group, "beatloop_size", loopSize / 2); - } else if (control === 53 && loopSize < 256) { // turn right - engine.setValue(this.group, "beatloop_size", loopSize * 2); - } - }; - } else { - this.input = function(channel, control, _value, _status, _group) { // if set to true invert function - var direction = (control === 52) ? "Down" : "Up"; //turn left: turn right - script.triggerControl("[Library]", "Move" + direction); - }; - } - }, - shift: function() { - if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.input = function(channel, control, _value, _status, _group) { - var direction = (control === 52) ? "Down" : "Up"; //turn left: turn right - script.triggerControl("[Library]", "Move" + direction); - }; - } else { - this.input = function(channel, control, _value, _status, _group) { // if set to true invert function - var loopSize = engine.getValue(this.group, "beatloop_size"); - if (control === 52 && loopSize >= (1/16)) { //turn left - engine.setValue(this.group, "beatloop_size", loopSize / 2); - } else if (control === 53 && loopSize < 256) { //turn right - engine.setValue(this.group, "beatloop_size", loopSize * 2); - } - }; - } - }, - }); - - this.loopEncoderButton = new components.Button({ - shift: function() { - if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.inKey = "LoadSelectedTrack"; - } else { - this.inKey = "beatloop_activate"; // if set to true invert function - } - }, - unshift: function() { - if (!NumarkScratch.invertLoopEncoderFunction) { //if set to false then normal function - this.inKey = "beatloop_activate"; - } else { - this.inKey = "LoadSelectedTrack"; // if set to true invert function - } + const encoderInvert = function(key) { + if (NumarkScratch.invertloopFunction) { + return key === "unshift" ? "shift" : "unshift"; } - }); + return key; + }; + + const loopPlusEncoderConf = { + midi: [0x93 + channel, 0x35], + }; + loopPlusEncoderConf[encoderInvert("unshift")] = function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "loop_double"; + }; + loopPlusEncoderConf[encoderInvert("shift")] = function() { + this.group = "[Library]"; + this.inKey = "MoveDown"; + }; + this.loopPlus = new components.Encoder(loopPlusEncoderConf); + + const loopMinusEncoderConf = { + midi: [0x93 + channel, 0x34], + }; + loopMinusEncoderConf[encoderInvert("unshift")] = function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "loop_halve"; + }; + loopMinusEncoderConf[encoderInvert("shift")] = function() { + this.group = "[Library]"; + this.inKey = "MoveUp"; + }; + this.loopMinus = new components.Encoder(loopMinusEncoderConf); + + const loopButtonConf = { + midi: [0x93 + channel, 0x3F], + }; + + loopButtonConf[encoderInvert("unshift")] = function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "beatloop_activate"; + }; + loopButtonConf[encoderInvert("shift")] = function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "LoadSelectedTrack"; + }; + this.loopButton = new components.Button(loopButtonConf); this.padSection = new NumarkScratch.PadSection(number); @@ -355,12 +347,12 @@ NumarkScratch.PadSection = function(deckNumber) { }; this.padPress = function(channel, control, value, status, group) { - var i = (control - 0x14) % 8; + const i = (control - 0x14) % 8; this.currentMode.pads[i].input(channel, control, value, status, group); }; this.setMode = function(_channel, control) { - var newMode = this.modes[control]; + const newMode = this.modes[control]; this.currentMode.forEachComponent(function(component) { component.disconnect(); }); @@ -383,7 +375,7 @@ NumarkScratch.ModeHotcue = function(deckNumber) { this.control = NumarkScratch.PadModeControls.HOTCUE; this.pads = new components.ComponentContainer(); - for (var i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { this.pads[i] = new components.HotcueButton({ group: "[Channel" + deckNumber + "]", midi: [0x93 + deckNumber, 0x14 + i], @@ -403,7 +395,7 @@ NumarkScratch.ModeRoll = function(deckNumber) { this.control = NumarkScratch.PadModeControls.ROLL; this.pads = new components.ComponentContainer(); - for (var i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { this.pads[i] = new components.Button({ group: "[Channel" + deckNumber + "]", midi: [0x93 + deckNumber, 0x14 + i], @@ -425,7 +417,7 @@ NumarkScratch.ModeSampler = function(deckNumber) { this.control = NumarkScratch.PadModeControls.SAMPLER; this.pads = new components.ComponentContainer(); - for (var i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { this.pads[i] = new components.SamplerButton({ midi: [0x93 + deckNumber, 0x14 + i], number: i + 1, diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index b94b89876293..b21fc3b07d71 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -667,7 +667,7 @@ [Channel1] - NumarkScratch.deck[0].loopEncoder.input + NumarkScratch.deck[0].loopMinus.input 0x94 0x34 @@ -676,7 +676,7 @@ [Channel1] - NumarkScratch.deck[0].loopEncoder.input + NumarkScratch.deck[0].loopPlus.input 0x94 0x35 @@ -685,7 +685,7 @@ [Channel2] - NumarkScratch.deck[1].loopEncoder.input + NumarkScratch.deck[1].loopMinus.input 0x95 0x34 @@ -694,54 +694,16 @@ [Channel2] - NumarkScratch.deck[1].loopEncoder.input + NumarkScratch.deck[1].loopPlus.input 0x95 0x35 - - - - [Channel1] - NumarkScratch.deck[0].loopEncoderButton.input + NumarkScratch.deck[0].loopButton.input 0x94 0x3F @@ -750,7 +712,7 @@ [Channel2] - NumarkScratch.deck[1].loopEncoderButton.input + NumarkScratch.deck[1].loopButton.input 0x95 0x3F @@ -760,7 +722,7 @@ [Channel1] - NumarkScratch.deck[0].loopEncoderButton.input + NumarkScratch.deck[0].loopButton.input 0x84 0x3F @@ -769,7 +731,7 @@ [Channel2] - NumarkScratch.deck[1].loopEncoderButton.input + NumarkScratch.deck[1].loopButton.input 0x85 0x3F From f76f9da86924a3507d4b7b352598520ce076068b Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sat, 18 Mar 2023 08:33:35 +1100 Subject: [PATCH 13/30] comments cleanup --- res/controllers/Numark-Scratch-scripts.js | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 750a4b0aa40d..e8152ea36b12 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -1,11 +1,12 @@ var NumarkScratch = {}; -///////////////// -// Tweakables. // -///////////////// +/* + * USER CONFIGURABLE SETTINGS. + */ -// Beatloop Roll sizes for the 4 pads, for available values see: -// https://manual.mixxx.org/2.3/en/chapters/appendix/mixxx_controls.html#control-[ChannelN]-beatloop_X_toggle +// Defines the Beatloop Roll sizes for the 4 pads, for available values see: +// https://manual.mixxx.org/2.4/en/chapters/appendix/mixxx_controls.html#control-[ChannelN]-beatlooproll_X_activate +// Default: [0.25, 0.5, 1, 2] NumarkScratch.autoLoopSizes = [ "0.25", "0.5", @@ -13,17 +14,20 @@ NumarkScratch.autoLoopSizes = [ "2", ]; -// Default is false. When set to false, the EncoderKnob manages looping. Shift + EncoderKnob scrolls the library/loads track -// If set to true, the EncoderKnob scrolls the library/loads track. Shift + EncoderKnob manages looping. +// Defines how the Loop Encoder functions. +// If 'true' the Encoder scrolls the library/loads track. Shift + Encoder manages looping. +// If 'false' the Encoder manages looping. Shift + Encoder scrolls the library/loads track (Serato default). +// Default: false NumarkScratch.invertLoopEncoderFunction = false; -// Turn off all when inactive instead default is 0x00 (Off) -// Set to 0x01 is you want lights to be dim +// Defines the bightness of button LEDs when they inactive. +// '0x00' sets the LEDSs to completely off. '0x01 sets the LEDs to dim. +// Default: 0x00 NumarkScratch.LOW_LIGHT = 0x00; -/////////// -// Code. // -/////////// +/* + * CODE + */ // State variable, don't touch NumarkScratch.shifted = false; From e2d93dde4456b03046c8f56257fbea79a4359874 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 11 Jun 2023 18:25:31 +1000 Subject: [PATCH 14/30] Move super1 to shift function of the dryWetKnob. --- res/controllers/Numark-Scratch-scripts.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index e8152ea36b12..a23f98572bf6 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -128,8 +128,6 @@ NumarkScratch.EffectUnit = function(deckNumber) { // 2 - switch down this.enableSwitch = function(channel, control, value, _status, _group) { this.isSwitchHoldOn = value !== 0; - engine.setValue("[EffectRack1_EffectUnit1]", "super1", Math.min(value, 1.0)); - engine.setValue("[EffectRack1_EffectUnit2]", "super1", Math.min(value, 1.0)); engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); this.updateEffects(); @@ -137,7 +135,12 @@ NumarkScratch.EffectUnit = function(deckNumber) { this.dryWetKnob = new components.Pot({ group: "[EffectRack1_EffectUnit" + deckNumber + "]", - inKey: "mix" + shift: function() { + this.inKey = "super1"; + }, + unshift: function() { + this.inKey = "mix"; + }, }); this.effect1 = function(channel, control, value, status, _group) { From e2717cc53d24de9f64996e7c1fbf93283bf36514 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 11 Jun 2023 20:03:19 +1000 Subject: [PATCH 15/30] Fix Typo --- res/controllers/Numark-Scratch-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index a23f98572bf6..861a222620fa 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -264,7 +264,7 @@ NumarkScratch.Deck = function(number) { }); const encoderInvert = function(key) { - if (NumarkScratch.invertloopFunction) { + if (NumarkScratch.invertloopEncoderFunction) { return key === "unshift" ? "shift" : "unshift"; } return key; From eda981951bb9ef137037b3d703d6413a2f8de0f9 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sat, 17 Jun 2023 16:25:34 +1000 Subject: [PATCH 16/30] Fix typo --- res/controllers/Numark-Scratch-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 861a222620fa..334ffa2b9ec0 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -264,7 +264,7 @@ NumarkScratch.Deck = function(number) { }); const encoderInvert = function(key) { - if (NumarkScratch.invertloopEncoderFunction) { + if (NumarkScratch.invertLoopEncoderFunction) { return key === "unshift" ? "shift" : "unshift"; } return key; From 4f5d541f198a209365b87a81919bd6e8a8ad03d7 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Mon, 19 Jun 2023 19:41:04 +1000 Subject: [PATCH 17/30] Move crossfader component to init --- res/controllers/Numark-Scratch-scripts.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 334ffa2b9ec0..3e8e98782069 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -43,8 +43,11 @@ NumarkScratch.init = function() { NumarkScratch.effect[i] = new NumarkScratch.EffectUnit(i + 1); } - // Send Serato SysEx messages to request initial state and unlock pads - midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); + NumarkScratch.crossfader = new components.Pot({ + midi: [0xBF, 0x08], + group: "[Master]", + inKey: "crossfader", + }); const createVuCallback = function(deckOffset) { return function(value) { @@ -71,6 +74,10 @@ NumarkScratch.init = function() { midi.sendShortMsg(0x99, 0x04, NumarkScratch.LOW_LIGHT); midi.sendShortMsg(0x99, 0x05, NumarkScratch.LOW_LIGHT); midi.sendShortMsg(0x9F, 0x32, NumarkScratch.LOW_LIGHT); + + // Send Serato SysEx messages to request initial state and unlock pads + midi.sendSysexMsg([0xF0, 0x00, 0x20, 0x7F, 0x00, 0xF7]); + }; NumarkScratch.shutdown = function() { @@ -180,12 +187,6 @@ NumarkScratch.EffectUnit = function(deckNumber) { }; NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); -NumarkScratch.crossfader = new components.Pot({ - midi: [0xBF, 0x08], - group: "[Master]", - inKey: "crossfader", -}); - NumarkScratch.crossfader.setCurve = function(channel, control, value, _status, _group) { switch (value) { case 0x00: // Additive/Linear From f791cb79fd675d662d989de7b23ad292aa7dd1b9 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sat, 24 Jun 2023 17:28:24 +1000 Subject: [PATCH 18/30] Create Crossfader component outside the init --- res/controllers/Numark-Scratch-scripts.js | 54 +++++++++++++---------- res/controllers/Numark-Scratch.midi.xml | 8 ++-- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 3e8e98782069..ae46b60bd9b7 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -43,11 +43,7 @@ NumarkScratch.init = function() { NumarkScratch.effect[i] = new NumarkScratch.EffectUnit(i + 1); } - NumarkScratch.crossfader = new components.Pot({ - midi: [0xBF, 0x08], - group: "[Master]", - inKey: "crossfader", - }); + NumarkScratch.xfader = new NumarkScratch.XfaderContainer(); const createVuCallback = function(deckOffset) { return function(value) { @@ -116,9 +112,9 @@ NumarkScratch.FxUpdateLEDs = function() { midi.sendShortMsg(0x99, 0x04, newStates2[1] ? 0x7F:NumarkScratch.LOW_LIGHT); midi.sendShortMsg(0x99, 0x05, newStates2[2] ? 0x7F:NumarkScratch.LOW_LIGHT); }; -// 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) +// TODO - it is not possible to "properly" map the FX selection buttons. +// solution should use proper OOP principles & incorporate global quickeffect chain preset, see +// https://github.com/mixxxdj/mixxx/pull/11378 NumarkScratch.EffectUnit = function(deckNumber) { this.effects = [false, false, false]; this.isSwitchHoldOn = false; @@ -187,25 +183,35 @@ NumarkScratch.EffectUnit = function(deckNumber) { }; NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); -NumarkScratch.crossfader.setCurve = function(channel, control, value, _status, _group) { - switch (value) { - case 0x00: // Additive/Linear - engine.setValue("[Mixer Profile]", "xFaderMode", 0); - engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.4); - engine.setValue("[Mixer Profile]", "xFaderCurve", 0.9); - break; - case 0x7F: // Picnic Bench/Fast Cut - engine.setValue("[Mixer Profile]", "xFaderMode", 0); - engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.9); - engine.setValue("[Mixer Profile]", "xFaderCurve", 7.0); - } -}; +NumarkScratch.XfaderContainer = function() { + this.crossfader = new components.Pot({ + midi: [0xBF, 0x08], + group: "[Master]", + inKey: "crossfader", + }); + + this.crossfader.setCurve = function(channel, control, value, _status, _group) { + switch (value) { + case 0x00: // Additive/Linear + engine.setValue("[Mixer Profile]", "xFaderMode", 0); + engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.4); + engine.setValue("[Mixer Profile]", "xFaderCurve", 0.9); + break; + case 0x7F: // Picnic Bench/Fast Cut + engine.setValue("[Mixer Profile]", "xFaderMode", 0); + engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.9); + engine.setValue("[Mixer Profile]", "xFaderCurve", 7.0); + } + }; -NumarkScratch.crossfader.xFaderReverse = function(channel, control, value, _status, _group) { - // 0x7F is ON, 0x00 is OFF - engine.setValue("[Mixer Profile]", "xFaderReverse", (value === 0x7F) ? 1 : 0); + this.crossfader.xFaderReverse = function(channel, control, value, _status, _group) { + // 0x7F is ON, 0x00 is OFF + engine.setValue("[Mixer Profile]", "xFaderReverse", (value === 0x7F) ? 1 : 0); + }; }; +NumarkScratch.XfaderContainer.prototype = new components.ComponentContainer(); + NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { const number = (control === 0x57) ? 1 : 2; const channelgroup = "[Channel" + number + "]"; diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index b21fc3b07d71..94e29526b311 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -59,7 +59,7 @@ [Master] - NumarkScratch.crossfader.input + NumarkScratch.xfader.crossfader.input 0xBF 0x08 @@ -191,7 +191,7 @@ [Mixer Profile] - NumarkScratch.crossfader.xFaderReverse + NumarkScratch.xfader.crossfader.xFaderReverse 0x9F 0x1E @@ -201,7 +201,7 @@ [Mixer Profile] - NumarkScratch.crossfader.xFaderReverse + NumarkScratch.xfader.crossfader.xFaderReverse 0x8F 0x1E @@ -211,7 +211,7 @@ [Mixer Profile] - NumarkScratch.crossfader.setCurve + NumarkScratch.xfader.crossfader.setCurve 0xBF 0x09 From 938b1ce17f9df261b08ada7fe48ac66d6c90c732 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 10 Sep 2023 10:26:45 +1000 Subject: [PATCH 19/30] refactor xfader component --- res/controllers/Numark-Scratch-scripts.js | 1 + res/controllers/Numark-Scratch.midi.xml | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index ae46b60bd9b7..8d67e097c261 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -201,6 +201,7 @@ NumarkScratch.XfaderContainer = function() { engine.setValue("[Mixer Profile]", "xFaderMode", 0); engine.setValue("[Mixer Profile]", "xFaderCalibration", 0.9); engine.setValue("[Mixer Profile]", "xFaderCurve", 7.0); + break; } }; diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index 94e29526b311..d1feb9bce68a 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -191,7 +191,7 @@ [Mixer Profile] - NumarkScratch.xfader.crossfader.xFaderReverse + NumarkScratch.xfader.xFaderReverse 0x9F 0x1E @@ -201,7 +201,7 @@ [Mixer Profile] - NumarkScratch.xfader.crossfader.xFaderReverse + NumarkScratch.xfader.xFaderReverse 0x8F 0x1E @@ -211,7 +211,7 @@ [Mixer Profile] - NumarkScratch.xfader.crossfader.setCurve + NumarkScratch.xfader.setCurve 0xBF 0x09 From 0b8b74115423fb3be66326c86cc242f70a02ee7d Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 10 Sep 2023 10:46:56 +1000 Subject: [PATCH 20/30] refactor xfader component fix --- res/controllers/Numark-Scratch-scripts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 8d67e097c261..36e7c099d496 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -190,7 +190,7 @@ NumarkScratch.XfaderContainer = function() { inKey: "crossfader", }); - this.crossfader.setCurve = function(channel, control, value, _status, _group) { + this.setCurve = function(channel, control, value, _status, _group) { switch (value) { case 0x00: // Additive/Linear engine.setValue("[Mixer Profile]", "xFaderMode", 0); @@ -205,7 +205,7 @@ NumarkScratch.XfaderContainer = function() { } }; - this.crossfader.xFaderReverse = function(channel, control, value, _status, _group) { + this.xFaderReverse = function(channel, control, value, _status, _group) { // 0x7F is ON, 0x00 is OFF engine.setValue("[Mixer Profile]", "xFaderReverse", (value === 0x7F) ? 1 : 0); }; From b6811b0a66cdd4970004982d86ebb6434ed3e752 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 10 Sep 2023 12:08:28 +1000 Subject: [PATCH 21/30] refactor effects --- res/controllers/Numark-Scratch-scripts.js | 127 +++++++++------------- res/controllers/Numark-Scratch.midi.xml | 28 ++--- 2 files changed, 68 insertions(+), 87 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 36e7c099d496..1a0b4e522cbe 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -1,4 +1,4 @@ -var NumarkScratch = {}; +const NumarkScratch = {}; /* * USER CONFIGURABLE SETTINGS. @@ -92,52 +92,68 @@ NumarkScratch.unshift = function() { NumarkScratch.effect.unshift(); }; -NumarkScratch.allEffectOff = function() { - NumarkScratch.effect[0].effects=[false, false, false]; - NumarkScratch.effect[1].effects=[false, false, false]; - NumarkScratch.FxUpdateLEDs(); - NumarkScratch.effect[0].updateEffects(); - NumarkScratch.effect[1].updateEffects(); -}; - -NumarkScratch.FxUpdateLEDs = function() { - let newStates1=[false, false, false]; - let newStates2=[false, false, false]; - newStates1=NumarkScratch.effect[0].effects; - newStates2=NumarkScratch.effect[1].effects; - midi.sendShortMsg(0x98, 0x00, newStates1[0] ? 0x7F:NumarkScratch.LOW_LIGHT); - midi.sendShortMsg(0x98, 0x01, newStates1[1] ? 0x7F:NumarkScratch.LOW_LIGHT); - midi.sendShortMsg(0x98, 0x02, newStates1[2] ? 0x7F:NumarkScratch.LOW_LIGHT); - midi.sendShortMsg(0x99, 0x03, newStates2[0] ? 0x7F:NumarkScratch.LOW_LIGHT); - midi.sendShortMsg(0x99, 0x04, newStates2[1] ? 0x7F:NumarkScratch.LOW_LIGHT); - midi.sendShortMsg(0x99, 0x05, newStates2[2] ? 0x7F:NumarkScratch.LOW_LIGHT); -}; -// TODO - it is not possible to "properly" map the FX selection buttons. -// solution should use proper OOP principles & incorporate global quickeffect chain preset, see -// https://github.com/mixxxdj/mixxx/pull/11378 NumarkScratch.EffectUnit = function(deckNumber) { - this.effects = [false, false, false]; - this.isSwitchHoldOn = false; - this.updateEffects = function() { - for (let i = 1; i <= this.effects.length; i++) { - engine.setValue("[EffectRack1_EffectUnit" + deckNumber + "_Effect"+i+"]", "enabled", this.effects[i-1]); + const inputUnshifted = function(channel, control, value, _status, _group) { + if (value !== 0x7F) { + return; } + // Enable the current button + engine.setValue(this.group, this.inKey, true); + + // Disable all other buttons in the same unit + NumarkScratch.effect[deckNumber - 1].effectButtons.forEach((effectButton) => { + if (effectButton !== this) { + engine.setValue(effectButton.group, effectButton.inKey, false); + } + }); + + // Disable all buttons in the other unit + NumarkScratch.effect[1 - (deckNumber - 1)].effectButtons.forEach((effectButton) => { + engine.setValue(effectButton.group, effectButton.inKey, false); + }); }; - // switch values are: - // 0 - switch in the middle - // 1 - switch up - // 2 - switch down - this.enableSwitch = function(channel, control, value, _status, _group) { - this.isSwitchHoldOn = value !== 0; - engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); - engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", (value !== 0)); - this.updateEffects(); + const inputShifted = function(channel, control, value, _status, _group) { + if (value === 0x7F) { + // Toggle the current button state + const currentState = engine.getValue(this.group, this.inKey); + engine.setValue(this.group, this.inKey, !currentState); + } }; + this.effectButtons = []; + for (let i = 0; i < 3; i++) { + this.effectButtons[i] = new components.Button({ + group: "[EffectRack1_EffectUnit" + deckNumber + "_Effect" + (i + 1) + "]", + midi: [0x98 + deckNumber - 1, deckNumber - 1 + i], + off: NumarkScratch.LOW_LIGHT, + inKey: "enabled", + input: inputUnshifted, + shift: function() { + this.input = inputShifted; + }, + unshift: function() { + this.input = inputUnshifted; + }, + }); + } + + this.paddle = new components.Button({ + group: "[EffectRack1_EffectUnit" + deckNumber + "]", + outKey: "enabled", + inKey: "group_[Channel" + deckNumber + "]_enable", + input: function(channel, control, value, _status, _group) { + this.isPress = value !== 0; + engine.setValue("[EffectRack1_EffectUnit1]", "group_[Channel" + deckNumber + "]_enable", this.isPress); + engine.setValue("[EffectRack1_EffectUnit2]", "group_[Channel" + deckNumber + "]_enable", this.isPress); + this.trigger(); + } + }); + this.dryWetKnob = new components.Pot({ group: "[EffectRack1_EffectUnit" + deckNumber + "]", + inKey: "mix", shift: function() { this.inKey = "super1"; }, @@ -145,41 +161,6 @@ NumarkScratch.EffectUnit = function(deckNumber) { this.inKey = "mix"; }, }); - - this.effect1 = function(channel, control, value, status, _group) { - if (value === 0x7F) { - if (!NumarkScratch.shifted) { - NumarkScratch.allEffectOff(); - } - this.effects[0] = !this.effects[0]; - midi.sendShortMsg(status, control, this.effects[0] ? 0x7F : NumarkScratch.LOW_LIGHT); - } - - this.updateEffects(); - }; - - this.effect2 = function(channel, control, value, status, _group) { - if (value === 0x7F) { - if (!NumarkScratch.shifted) { - NumarkScratch.allEffectOff(); - } - this.effects[1] = !this.effects[1]; - midi.sendShortMsg(status, control, this.effects[1] ? 0x7F : NumarkScratch.LOW_LIGHT); - } - - this.updateEffects(); - }; - - this.effect3 = function(channel, control, value, status, _group) { - if (value === 0x7F) { - if (!NumarkScratch.shifted) { - NumarkScratch.allEffectOff(); - } - this.effects[2] = !this.effects[2]; - midi.sendShortMsg(status, control, this.effects[2] ? 0x7F : NumarkScratch.LOW_LIGHT); - } - this.updateEffects(); - }; }; NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index d1feb9bce68a..7cb80c3cf23a 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -760,7 +760,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect1 + NumarkScratch.effect[0].effectButtons[0].input 0x98 0x00 @@ -770,7 +770,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect1 + NumarkScratch.effect[0].effectButtons[0].input 0x88 0x00 @@ -780,7 +780,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect2 + NumarkScratch.effect[0].effectButtons[1].input 0x98 0x01 @@ -790,7 +790,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect2 + NumarkScratch.effect[0].effectButtons[1].input 0x88 0x01 @@ -800,7 +800,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect3 + NumarkScratch.effect[0].effectButtons[2].input 0x98 0x02 @@ -810,7 +810,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].effect3 + NumarkScratch.effect[0].effectButtons[2].input 0x88 0x02 @@ -820,7 +820,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect1 + NumarkScratch.effect[1].effectButtons[0].input 0x99 0x03 @@ -830,7 +830,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect1 + NumarkScratch.effect[1].effectButtons[0].input 0x89 0x03 @@ -840,7 +840,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect2 + NumarkScratch.effect[1].effectButtons[1].input 0x99 0x04 @@ -850,7 +850,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect2 + NumarkScratch.effect[1].effectButtons[1].input 0x89 0x04 @@ -860,7 +860,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect3 + NumarkScratch.effect[1].effectButtons[2].input 0x99 0x05 @@ -870,7 +870,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].effect3 + NumarkScratch.effect[1].effectButtons[2].input 0x89 0x05 @@ -880,7 +880,7 @@ [EffectRack1_EffectUnit1] - NumarkScratch.effect[0].enableSwitch + NumarkScratch.effect[0].paddle.input 0xB8 0x03 @@ -889,7 +889,7 @@ [EffectRack1_EffectUnit2] - NumarkScratch.effect[1].enableSwitch + NumarkScratch.effect[1].paddle.input 0xB9 0x03 From 364e25973cd9792cdb80531b4ba5307f51dfb338 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 10 Sep 2023 12:30:34 +1000 Subject: [PATCH 22/30] fix pre-commit mess up on controller declaration --- res/controllers/Numark-Scratch-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 1a0b4e522cbe..5c679d2ffb10 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -1,4 +1,4 @@ -const NumarkScratch = {}; +var NumarkScratch = {}; /* * USER CONFIGURABLE SETTINGS. From 19748742adb6ded2d3882433e84ee6229c605074 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 10 Sep 2023 14:29:12 +1000 Subject: [PATCH 23/30] minor refactor --- res/controllers/Numark-Scratch-scripts.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 5c679d2ffb10..b8f706198883 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -22,8 +22,8 @@ NumarkScratch.invertLoopEncoderFunction = false; // Defines the bightness of button LEDs when they inactive. // '0x00' sets the LEDSs to completely off. '0x01 sets the LEDs to dim. -// Default: 0x00 -NumarkScratch.LOW_LIGHT = 0x00; +// Default: 0x01 (dim) +NumarkScratch.LOW_LIGHT = 0x01; /* * CODE @@ -126,9 +126,9 @@ NumarkScratch.EffectUnit = function(deckNumber) { for (let i = 0; i < 3; i++) { this.effectButtons[i] = new components.Button({ group: "[EffectRack1_EffectUnit" + deckNumber + "_Effect" + (i + 1) + "]", - midi: [0x98 + deckNumber - 1, deckNumber - 1 + i], - off: NumarkScratch.LOW_LIGHT, + midi: [0x98 + deckNumber - 1, (deckNumber - 1) * 3 + i], inKey: "enabled", + outKey: "enabled", // Bind the LED state to the effect enabled state input: inputUnshifted, shift: function() { this.input = inputShifted; From 007b9ee84d2d6a1af2e451cb172380fe84d68e9e Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sat, 16 Sep 2023 15:45:28 +1000 Subject: [PATCH 24/30] refactor channel input selector --- res/controllers/Numark-Scratch-scripts.js | 39 +++++++++++++---------- res/controllers/Numark-Scratch.midi.xml | 16 +++++----- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index b8f706198883..53adcb6e763d 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-var var NumarkScratch = {}; /* @@ -194,27 +195,33 @@ NumarkScratch.XfaderContainer = function() { NumarkScratch.XfaderContainer.prototype = new components.ComponentContainer(); -NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { - const number = (control === 0x57) ? 1 : 2; - const channelgroup = "[Channel" + number + "]"; - - switch (value) { - case 0x00: // PC and turn on vinyl control - engine.setValue(channelgroup, "passthrough", 0); - engine.setValue(channelgroup, "vinylcontrol_enabled", 1); - break; - case 0x02: // PHONO/LINE and turn off vinyl control - engine.setValue(channelgroup, "passthrough", 1); - engine.setValue(channelgroup, "vinylcontrol_enabled", 0); - break; - } -}; - NumarkScratch.Deck = function(number) { components.Deck.call(this, number); const channel = number; + this.channelInputPC = new components.Button({ + group: "[Channel" + number + "]", + input: function(channel, control, value, status, group) { + if (value === 0x7F) { + // Set vinyl control enabled and passthrough disabled + engine.setValue(group, "vinylcontrol_enabled", 1); + engine.setValue(group, "passthrough", 0); + } + } + }); + + this.channelInputLinePhono = new components.Button({ + group: "[Channel" + number + "]", + input: function(channel, control, value, status, group) { + if (value === 0x7F) { + // Set vinyl control disabled and passthrough enabled + engine.setValue(group, "vinylcontrol_enabled", 0); + engine.setValue(group, "passthrough", 1); + } + } + }); + this.pflButton = new components.Button({ midi: [0x90 + channel, 0x1B], key: "pfl", diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index 7cb80c3cf23a..c5729ffc9325 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -16,8 +16,8 @@ - [Master] - NumarkScratch.setChannelInput + [Channel1] + NumarkScratch.deck[0].channelInputPC.input CH 1 PC 0x8F 0x57 @@ -26,8 +26,8 @@ - [Master] - NumarkScratch.setChannelInput + [Channel1] + NumarkScratch.deck[0].channelInputLinePhono.input CH 1 LINE/PHONO 0x9F 0x57 @@ -37,8 +37,8 @@ - [Master] - NumarkScratch.setChannelInput + [Channel2] + NumarkScratch.deck[1].channelInputPC.input CH 2 PC 0x8F 0x60 @@ -47,8 +47,8 @@ - [Master] - NumarkScratch.setChannelInput + [Channel2] + NumarkScratch.deck[1].channelInputLinePhono.input CH 2 LINE/PHONO 0x9F 0x60 From c44712654a9b28ebca52544833e2ac6ca5d0479a Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sat, 16 Sep 2023 16:08:15 +1000 Subject: [PATCH 25/30] fix channel input values --- res/controllers/Numark-Scratch-scripts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 53adcb6e763d..e076c67e62f4 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -203,7 +203,7 @@ NumarkScratch.Deck = function(number) { this.channelInputPC = new components.Button({ group: "[Channel" + number + "]", input: function(channel, control, value, status, group) { - if (value === 0x7F) { + if (value === 0x00) { // Set vinyl control enabled and passthrough disabled engine.setValue(group, "vinylcontrol_enabled", 1); engine.setValue(group, "passthrough", 0); @@ -214,7 +214,7 @@ NumarkScratch.Deck = function(number) { this.channelInputLinePhono = new components.Button({ group: "[Channel" + number + "]", input: function(channel, control, value, status, group) { - if (value === 0x7F) { + if (value === 0x02) { // Set vinyl control disabled and passthrough enabled engine.setValue(group, "vinylcontrol_enabled", 0); engine.setValue(group, "passthrough", 1); From 915b97ec0eeafd67a667256d64c193bb4658ec98 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Mon, 6 Nov 2023 18:56:10 +1100 Subject: [PATCH 26/30] Update deprecated COs --- res/controllers/Numark-Scratch-scripts.js | 6 +++--- res/controllers/Numark-Scratch.midi.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index e076c67e62f4..bbf1dd1b4cc6 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -52,8 +52,8 @@ NumarkScratch.init = function() { }; }; - engine.makeConnection("[Channel1]", "VuMeter", createVuCallback(0)); - engine.makeConnection("[Channel2]", "VuMeter", createVuCallback(1)); + engine.makeConnection("[Channel1]", "vu_meter", createVuCallback(0)); + engine.makeConnection("[Channel2]", "vu_meter", createVuCallback(1)); // Trigger is needed to initialize lights to 0x01 NumarkScratch.deck.forEachComponent(function(component) { @@ -168,7 +168,7 @@ NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); NumarkScratch.XfaderContainer = function() { this.crossfader = new components.Pot({ midi: [0xBF, 0x08], - group: "[Master]", + group: "[Mixer]", inKey: "crossfader", }); diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index c5729ffc9325..74570efbdacb 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -58,7 +58,7 @@ - [Master] + [Mixer] NumarkScratch.xfader.crossfader.input 0xBF 0x08 @@ -68,7 +68,7 @@ - [Master] + [Mixer] headMix 0xBF 0x0D From 4b7a70486eeff16541b2ab92ec95a42dc8895a6f Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 21 Apr 2024 14:10:04 +1000 Subject: [PATCH 27/30] revert CO change --- res/controllers/Numark-Scratch-scripts.js | 2 +- res/controllers/Numark-Scratch.midi.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index bbf1dd1b4cc6..97f4756b934c 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -168,7 +168,7 @@ NumarkScratch.EffectUnit.prototype = new components.ComponentContainer(); NumarkScratch.XfaderContainer = function() { this.crossfader = new components.Pot({ midi: [0xBF, 0x08], - group: "[Mixer]", + group: "[Master]", inKey: "crossfader", }); diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index 74570efbdacb..c5729ffc9325 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -58,7 +58,7 @@ - [Mixer] + [Master] NumarkScratch.xfader.crossfader.input 0xBF 0x08 @@ -68,7 +68,7 @@ - [Mixer] + [Master] headMix 0xBF 0x0D From 87b4e5860efd6161897947d25381712237995bd3 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 21 Apr 2024 15:11:20 +1000 Subject: [PATCH 28/30] revert older commit revert commit 8a9af48386757c24e360cf55af3a4002fe307dbc --- res/controllers/Numark-Scratch-scripts.js | 40 ++++++++++------------- res/controllers/Numark-Scratch.midi.xml | 16 ++++----- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 97f4756b934c..0a516cced61e 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -195,33 +195,29 @@ NumarkScratch.XfaderContainer = function() { NumarkScratch.XfaderContainer.prototype = new components.ComponentContainer(); +NumarkScratch.setChannelInput = function(channel, control, value, _status, _group) { + const number = (control === 0x57) ? 1 : 2; + const channelgroup = "[Channel" + number + "]"; + + switch (value) { + case 0x00: // PC and turn on vinyl control + engine.setValue(channelgroup, "passthrough", 0); + engine.setValue(channelgroup, "vinylcontrol_enabled", 1); + break; + case 0x02: // PHONO/LINE and turn off vinyl control + engine.setValue(channelgroup, "passthrough", 1); + engine.setValue(channelgroup, "vinylcontrol_enabled", 0); + break; + } +}; + +NumarkScratch.XfaderContainer.prototype = new components.ComponentContainer(); + NumarkScratch.Deck = function(number) { components.Deck.call(this, number); const channel = number; - this.channelInputPC = new components.Button({ - group: "[Channel" + number + "]", - input: function(channel, control, value, status, group) { - if (value === 0x00) { - // Set vinyl control enabled and passthrough disabled - engine.setValue(group, "vinylcontrol_enabled", 1); - engine.setValue(group, "passthrough", 0); - } - } - }); - - this.channelInputLinePhono = new components.Button({ - group: "[Channel" + number + "]", - input: function(channel, control, value, status, group) { - if (value === 0x02) { - // Set vinyl control disabled and passthrough enabled - engine.setValue(group, "vinylcontrol_enabled", 0); - engine.setValue(group, "passthrough", 1); - } - } - }); - this.pflButton = new components.Button({ midi: [0x90 + channel, 0x1B], key: "pfl", diff --git a/res/controllers/Numark-Scratch.midi.xml b/res/controllers/Numark-Scratch.midi.xml index c5729ffc9325..7cb80c3cf23a 100644 --- a/res/controllers/Numark-Scratch.midi.xml +++ b/res/controllers/Numark-Scratch.midi.xml @@ -16,8 +16,8 @@ - [Channel1] - NumarkScratch.deck[0].channelInputPC.input + [Master] + NumarkScratch.setChannelInput CH 1 PC 0x8F 0x57 @@ -26,8 +26,8 @@ - [Channel1] - NumarkScratch.deck[0].channelInputLinePhono.input + [Master] + NumarkScratch.setChannelInput CH 1 LINE/PHONO 0x9F 0x57 @@ -37,8 +37,8 @@ - [Channel2] - NumarkScratch.deck[1].channelInputPC.input + [Master] + NumarkScratch.setChannelInput CH 2 PC 0x8F 0x60 @@ -47,8 +47,8 @@ - [Channel2] - NumarkScratch.deck[1].channelInputLinePhono.input + [Master] + NumarkScratch.setChannelInput CH 2 LINE/PHONO 0x9F 0x60 From 0e898d9ca4322b8132d2da5985ab9c3264817c9a Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 19 May 2024 11:14:34 +1000 Subject: [PATCH 29/30] refactor loop encoder --- res/controllers/Numark-Scratch-scripts.js | 71 ++++++++++------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 0a516cced61e..8a62950c0bef 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -255,52 +255,45 @@ NumarkScratch.Deck = function(number) { inKey: "pregain" }); - const encoderInvert = function(key) { - if (NumarkScratch.invertLoopEncoderFunction) { - return key === "unshift" ? "shift" : "unshift"; - } - return key; + const encoderInvert = function(key) { + return NumarkScratch.invertLoopEncoderFunction ? (key === "unshift" ? "shift" : "unshift") : key; }; - const loopPlusEncoderConf = { + this.loopPlus = new components.Encoder({ midi: [0x93 + channel, 0x35], - }; - loopPlusEncoderConf[encoderInvert("unshift")] = function() { - this.group = "[Channel" + channel + "]"; - this.inKey = "loop_double"; - }; - loopPlusEncoderConf[encoderInvert("shift")] = function() { - this.group = "[Library]"; - this.inKey = "MoveDown"; - }; - this.loopPlus = new components.Encoder(loopPlusEncoderConf); + [encoderInvert("unshift")]: function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "loop_double"; + }, + [encoderInvert("shift")]: function() { + this.group = "[Library]"; + this.inKey = "MoveDown"; + } + }); - const loopMinusEncoderConf = { + this.loopMinus = new components.Encoder({ midi: [0x93 + channel, 0x34], - }; - loopMinusEncoderConf[encoderInvert("unshift")] = function() { - this.group = "[Channel" + channel + "]"; - this.inKey = "loop_halve"; - }; - loopMinusEncoderConf[encoderInvert("shift")] = function() { - this.group = "[Library]"; - this.inKey = "MoveUp"; - }; - this.loopMinus = new components.Encoder(loopMinusEncoderConf); + [encoderInvert("unshift")]: function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "loop_halve"; + }, + [encoderInvert("shift")]: function() { + this.group = "[Library]"; + this.inKey = "MoveUp"; + } + }); - const loopButtonConf = { + this.loopButton = new components.Button({ midi: [0x93 + channel, 0x3F], - }; - - loopButtonConf[encoderInvert("unshift")] = function() { - this.group = "[Channel" + channel + "]"; - this.inKey = "beatloop_activate"; - }; - loopButtonConf[encoderInvert("shift")] = function() { - this.group = "[Channel" + channel + "]"; - this.inKey = "LoadSelectedTrack"; - }; - this.loopButton = new components.Button(loopButtonConf); + [encoderInvert("unshift")]: function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "beatloop_activate"; + }, + [encoderInvert("shift")]: function() { + this.group = "[Channel" + channel + "]"; + this.inKey = "LoadSelectedTrack"; + } + }); this.padSection = new NumarkScratch.PadSection(number); From e11a8a46f8c51528642cafdc848d8daeecf4a400 Mon Sep 17 00:00:00 2001 From: Al Hadebe Date: Sun, 19 May 2024 11:28:53 +1000 Subject: [PATCH 30/30] refactor loop encoder --- res/controllers/Numark-Scratch-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Numark-Scratch-scripts.js b/res/controllers/Numark-Scratch-scripts.js index 8a62950c0bef..d2ef52b146db 100644 --- a/res/controllers/Numark-Scratch-scripts.js +++ b/res/controllers/Numark-Scratch-scripts.js @@ -255,7 +255,7 @@ NumarkScratch.Deck = function(number) { inKey: "pregain" }); - const encoderInvert = function(key) { + const encoderInvert = function(key) { return NumarkScratch.invertLoopEncoderFunction ? (key === "unshift" ? "shift" : "unshift") : key; };