From 558877d8c0bc83d17b606465551b51245eec8915 Mon Sep 17 00:00:00 2001 From: Olivier Mauras Date: Sat, 1 Jul 2023 21:17:03 +0200 Subject: [PATCH 1/5] Traktor Kontrol S2MK3: Use FX select buttons to set quick effect presets --- .../Traktor-Kontrol-S2-MK3-hid-scripts.js | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js index 704cabf2a71..315ad854e9f 100644 --- a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js +++ b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js @@ -1,6 +1,11 @@ /////////////////////////////////////////////////////////////////////////////////// // JSHint configuration // /////////////////////////////////////////////////////////////////////////////////// +/* global engine */ +/* global script */ +/* global HIDDebug */ +/* global HIDPacket */ +/* global HIDController */ /* jshint -W016 */ /////////////////////////////////////////////////////////////////////////////////// /* */ @@ -674,15 +679,41 @@ TraktorS2MK3.fxHandler = function(field) { return; } - const fxNumber = parseInt(field.id[field.id.length - 1]); - const group = "[EffectRack1_EffectUnit" + fxNumber + "]"; + const availableGroups = [ "[Channel1]", "[Channel2]" ]; + let targetGroups = []; + let fxNumber = parseInt(field.id[field.id.length - 1]); - // Toggle effect unit - TraktorS2MK3.fxButtonState[fxNumber] = !TraktorS2MK3.fxButtonState[fxNumber]; + // Target decks whose shift button is pressed. + for (let group of availableGroups) { + if (TraktorS2MK3.shiftPressed[group]) targetGroups.push(group); + } + + // If no shift button was pressed fall back to target all decks. + if (targetGroups.length === 0) targetGroups = availableGroups; + + for (let group of targetGroups) { + engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxNumber); + } +}; + +TraktorS2MK3.fxOutputHandler = function() { + const fxButtonCount = 4; + const availableGroups = [ "[Channel1]", "[Channel2]" ]; - engine.setValue(group, "group_[Channel1]_enable", TraktorS2MK3.fxButtonState[fxNumber]); - engine.setValue(group, "group_[Channel2]_enable", TraktorS2MK3.fxButtonState[fxNumber]); - TraktorS2MK3.outputHandler(TraktorS2MK3.fxButtonState[fxNumber], field.group, "fxButton" + fxNumber); + let activeFx = {}; + for (let group of availableGroups) { + activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); + } + + /* There is no way on the controller to indicate which deck the effect applies * + * to, but keeping both lit indicates that different effects are in use. */ + for (let fxButton = 1; fxButton <= fxButtonCount; ++fxButton) { + let active = false; + for (let group of availableGroups) { + active = active || activeFx[group] === fxButton; + } + TraktorS2MK3.outputHandler(active, "[ChannelX]", "fxButton" + fxButton); + } }; TraktorS2MK3.reverseHandler = function(field) { @@ -836,6 +867,11 @@ TraktorS2MK3.registerOutputPackets = function() { this.samplerCallbacks.push(engine.makeConnection("[Sampler" + i + "]", "play", this.samplesOutputHandler)); } + this.fxCallbacks = []; + for (let group of [ "[Channel1]", "[Channel2]" ]) { + this.fxCallbacks.push(engine.makeConnection(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", this.fxOutputHandler)); + } + TraktorS2MK3.lightDeck(false); }; @@ -1015,6 +1051,8 @@ TraktorS2MK3.lightDeck = function(switchOff) { TraktorS2MK3.controller.setOutput("[ChannelX]", "fxButton2", softLight, false); TraktorS2MK3.controller.setOutput("[ChannelX]", "fxButton3", softLight, false); TraktorS2MK3.controller.setOutput("[ChannelX]", "fxButton4", softLight, false); + // Set FX button LED state according to active quick effects on start-up + if (!switchOff) TraktorS2MK3.fxOutputHandler(); TraktorS2MK3.controller.setOutput("[Channel1]", "reverse", softLight, false); TraktorS2MK3.controller.setOutput("[Channel2]", "reverse", softLight, false); From 8fd6470ef8610d964b504ed071068bf7aeb92a8e Mon Sep 17 00:00:00 2001 From: Olivier Mauras Date: Sun, 2 Jul 2023 00:35:01 +0200 Subject: [PATCH 2/5] Traktor Kontrol S2MK3: Add second FX per button --- .../Traktor-Kontrol-S2-MK3-hid-scripts.js | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js index 315ad854e9f..f0ac1b42d1e 100644 --- a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js +++ b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js @@ -675,13 +675,19 @@ TraktorS2MK3.wheelDeltas = function(deckNumber, value) { }; TraktorS2MK3.fxHandler = function(field) { + /* We support 8 effects in total by having 2 effects per fx button. * + * First press of the button will load the preset at the index of the quick effect preset list * + * Second press will load the preset index + 4 * + * Arrange your quick effect preset list from 1 to 8 like this: 1/5, 2/6, 3/7, 4/8 */ if (field.value === 0) { return; } const availableGroups = [ "[Channel1]", "[Channel2]" ]; + const fxButtonCount = 4; let targetGroups = []; let fxNumber = parseInt(field.id[field.id.length - 1]); + let noShift = false; // Target decks whose shift button is pressed. for (let group of availableGroups) { @@ -689,10 +695,49 @@ TraktorS2MK3.fxHandler = function(field) { } // If no shift button was pressed fall back to target all decks. - if (targetGroups.length === 0) targetGroups = availableGroups; + if (targetGroups.length === 0) { + targetGroups = availableGroups; + noShift = true; + } + + let fxToApply = {}; + let activeFx = {}; + // Detect which fx should be enabled + for (let group of targetGroups) { + activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); + if (activeFx[group] === fxNumber) { + // Pressing again the fx button + fxToApply[group] = fxNumber + fxButtonCount; + } else if (activeFx[group] === fxNumber + fxButtonCount) { + // Already on secondary fx so reseting back to fxNumber + fxToApply[group] = fxNumber; + } else { + // First press of a different fx button + fxToApply[group] = fxNumber; + } + } + + /* When we target both decks - No shift pressed - we want * + * to reset fx to same value for both */ + if (targetGroups.length === 2 && noShift) { + const [deck1, deck2] = targetGroups; + const activeFxDeck1 = activeFx[deck1]; + const activeFxDeck2 = activeFx[deck2]; + const fxToApplyDeck1 = fxToApply[deck1]; + const fxToApplyDeck2 = fxToApply[deck2]; + + // If any of deck has already fx enabled but different value to apply + if ((activeFxDeck1 === fxNumber || activeFxDeck2 === fxNumber) && fxToApplyDeck1 !== fxToApplyDeck2) { + // find lower value to reset both to the same one + const fxToApplyAll = Math.min(fxToApplyDeck1, fxToApplyDeck2); + fxToApply[deck1] = fxToApplyAll; + fxToApply[deck2] = fxToApplyAll; + } + } + // Now apply the new fx value for (let group of targetGroups) { - engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxNumber); + engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxToApply[group]); } }; @@ -703,6 +748,8 @@ TraktorS2MK3.fxOutputHandler = function() { let activeFx = {}; for (let group of availableGroups) { activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); + // We want to lit the proper fx button even when we have applied a higher fxNumber + if (activeFx[group] > fxButtonCount) activeFx[group] = activeFx[group] - fxButtonCount } /* There is no way on the controller to indicate which deck the effect applies * From 4d57b22382c06d99c4561c27267d303f762d4f90 Mon Sep 17 00:00:00 2001 From: Olivier Mauras Date: Sun, 2 Jul 2023 01:35:48 +0200 Subject: [PATCH 3/5] Traktor Kontrol S2MK3: Fix code style with pre-commit patch --- .../Traktor-Kontrol-S2-MK3-hid-scripts.js | 77 +++++++++---------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js index f0ac1b42d1e..7fbff86e616 100644 --- a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js +++ b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js @@ -1,11 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // JSHint configuration // /////////////////////////////////////////////////////////////////////////////////// -/* global engine */ -/* global script */ -/* global HIDDebug */ -/* global HIDPacket */ -/* global HIDController */ /* jshint -W016 */ /////////////////////////////////////////////////////////////////////////////////// /* */ @@ -683,80 +678,80 @@ TraktorS2MK3.fxHandler = function(field) { return; } - const availableGroups = [ "[Channel1]", "[Channel2]" ]; + const availableGroups = ["[Channel1]", "[Channel2]"]; const fxButtonCount = 4; let targetGroups = []; - let fxNumber = parseInt(field.id[field.id.length - 1]); + const fxNumber = parseInt(field.id[field.id.length - 1]); let noShift = false; // Target decks whose shift button is pressed. - for (let group of availableGroups) { - if (TraktorS2MK3.shiftPressed[group]) targetGroups.push(group); + for (const group of availableGroups) { + if (TraktorS2MK3.shiftPressed[group]) { targetGroups.push(group); } } // If no shift button was pressed fall back to target all decks. if (targetGroups.length === 0) { - targetGroups = availableGroups; - noShift = true; + targetGroups = availableGroups; + noShift = true; } - let fxToApply = {}; - let activeFx = {}; + const fxToApply = {}; + const activeFx = {}; // Detect which fx should be enabled - for (let group of targetGroups) { + for (const group of targetGroups) { activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); if (activeFx[group] === fxNumber) { - // Pressing again the fx button - fxToApply[group] = fxNumber + fxButtonCount; + // Pressing again the fx button + fxToApply[group] = fxNumber + fxButtonCount; } else if (activeFx[group] === fxNumber + fxButtonCount) { - // Already on secondary fx so reseting back to fxNumber - fxToApply[group] = fxNumber; + // Already on secondary fx so reseting back to fxNumber + fxToApply[group] = fxNumber; } else { - // First press of a different fx button - fxToApply[group] = fxNumber; + // First press of a different fx button + fxToApply[group] = fxNumber; } } /* When we target both decks - No shift pressed - we want * * to reset fx to same value for both */ if (targetGroups.length === 2 && noShift) { - const [deck1, deck2] = targetGroups; - const activeFxDeck1 = activeFx[deck1]; - const activeFxDeck2 = activeFx[deck2]; - const fxToApplyDeck1 = fxToApply[deck1]; - const fxToApplyDeck2 = fxToApply[deck2]; - - // If any of deck has already fx enabled but different value to apply - if ((activeFxDeck1 === fxNumber || activeFxDeck2 === fxNumber) && fxToApplyDeck1 !== fxToApplyDeck2) { + const [deck1, deck2] = targetGroups; + const activeFxDeck1 = activeFx[deck1]; + const activeFxDeck2 = activeFx[deck2]; + const fxToApplyDeck1 = fxToApply[deck1]; + const fxToApplyDeck2 = fxToApply[deck2]; + + // If any of deck has already fx enabled but different value to apply + if ((activeFxDeck1 === fxNumber || activeFxDeck2 === fxNumber) && fxToApplyDeck1 !== fxToApplyDeck2) { // find lower value to reset both to the same one - const fxToApplyAll = Math.min(fxToApplyDeck1, fxToApplyDeck2); - fxToApply[deck1] = fxToApplyAll; - fxToApply[deck2] = fxToApplyAll; - } + const fxToApplyAll = Math.min(fxToApplyDeck1, fxToApplyDeck2); + fxToApply[deck1] = fxToApplyAll; + fxToApply[deck2] = fxToApplyAll; + } } // Now apply the new fx value - for (let group of targetGroups) { - engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxToApply[group]); + for (const group of targetGroups) { + engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxToApply[group]); } }; TraktorS2MK3.fxOutputHandler = function() { const fxButtonCount = 4; - const availableGroups = [ "[Channel1]", "[Channel2]" ]; + const availableGroups = ["[Channel1]", "[Channel2]"]; - let activeFx = {}; - for (let group of availableGroups) { + const activeFx = {}; + for (const group of availableGroups) { activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); // We want to lit the proper fx button even when we have applied a higher fxNumber - if (activeFx[group] > fxButtonCount) activeFx[group] = activeFx[group] - fxButtonCount + if (activeFx[group] > fxButtonCount) { activeFx[group] = activeFx[group] - fxButtonCount; } } /* There is no way on the controller to indicate which deck the effect applies * * to, but keeping both lit indicates that different effects are in use. */ for (let fxButton = 1; fxButton <= fxButtonCount; ++fxButton) { let active = false; - for (let group of availableGroups) { + for (const group of availableGroups) { active = active || activeFx[group] === fxButton; } TraktorS2MK3.outputHandler(active, "[ChannelX]", "fxButton" + fxButton); @@ -915,7 +910,7 @@ TraktorS2MK3.registerOutputPackets = function() { } this.fxCallbacks = []; - for (let group of [ "[Channel1]", "[Channel2]" ]) { + for (const group of ["[Channel1]", "[Channel2]"]) { this.fxCallbacks.push(engine.makeConnection(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", this.fxOutputHandler)); } @@ -1099,7 +1094,7 @@ TraktorS2MK3.lightDeck = function(switchOff) { TraktorS2MK3.controller.setOutput("[ChannelX]", "fxButton3", softLight, false); TraktorS2MK3.controller.setOutput("[ChannelX]", "fxButton4", softLight, false); // Set FX button LED state according to active quick effects on start-up - if (!switchOff) TraktorS2MK3.fxOutputHandler(); + if (!switchOff) { TraktorS2MK3.fxOutputHandler(); } TraktorS2MK3.controller.setOutput("[Channel1]", "reverse", softLight, false); TraktorS2MK3.controller.setOutput("[Channel2]", "reverse", softLight, false); From 5902e7bed796e827e0287e33fc1f3b17a57923b4 Mon Sep 17 00:00:00 2001 From: Olivier Mauras Date: Sun, 2 Jul 2023 18:19:44 +0200 Subject: [PATCH 4/5] Traktor Kontrol S2MK3: Fix comment syntax --- res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js index 7fbff86e616..b9f1e6ba63a 100644 --- a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js +++ b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js @@ -704,7 +704,7 @@ TraktorS2MK3.fxHandler = function(field) { // Pressing again the fx button fxToApply[group] = fxNumber + fxButtonCount; } else if (activeFx[group] === fxNumber + fxButtonCount) { - // Already on secondary fx so reseting back to fxNumber + // Already on secondary fx so resetting back to fxNumber fxToApply[group] = fxNumber; } else { // First press of a different fx button From e861a5d1b5d317606b3acfab2df24bb7f6b484b9 Mon Sep 17 00:00:00 2001 From: Olivier Mauras Date: Sun, 2 Jul 2023 18:39:07 +0200 Subject: [PATCH 5/5] Traktor Kontrol S2MK3: Support '---' as first item of the list --- res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js index b9f1e6ba63a..7b3a552b95b 100644 --- a/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js +++ b/res/controllers/Traktor-Kontrol-S2-MK3-hid-scripts.js @@ -699,7 +699,7 @@ TraktorS2MK3.fxHandler = function(field) { const activeFx = {}; // Detect which fx should be enabled for (const group of targetGroups) { - activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); + activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset") - 1; if (activeFx[group] === fxNumber) { // Pressing again the fx button fxToApply[group] = fxNumber + fxButtonCount; @@ -732,7 +732,7 @@ TraktorS2MK3.fxHandler = function(field) { // Now apply the new fx value for (const group of targetGroups) { - engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxToApply[group]); + engine.setValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset", fxToApply[group] + 1); } }; @@ -742,7 +742,7 @@ TraktorS2MK3.fxOutputHandler = function() { const activeFx = {}; for (const group of availableGroups) { - activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset"); + activeFx[group] = engine.getValue(`[QuickEffectRack1_${group}]`, "loaded_chain_preset") - 1; // We want to lit the proper fx button even when we have applied a higher fxNumber if (activeFx[group] > fxButtonCount) { activeFx[group] = activeFx[group] - fxButtonCount; } }