From 69b9066ab8f0ce1e3375df0ff6810410a01043f4 Mon Sep 17 00:00:00 2001 From: Arthur Vimond Date: Fri, 7 Mar 2025 11:13:24 +0100 Subject: [PATCH 1/4] fix(controllers): fix crossfader cut on Traktor Kontrol Z1 This fixes the issue #14450 (https://github.com/mixxxdj/mixxx/issues/14450) --- res/controllers/Traktor-Kontrol-Z1-scripts.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/res/controllers/Traktor-Kontrol-Z1-scripts.js b/res/controllers/Traktor-Kontrol-Z1-scripts.js index b5e32e58fd81..a9c4d6606adb 100644 --- a/res/controllers/Traktor-Kontrol-Z1-scripts.js +++ b/res/controllers/Traktor-Kontrol-Z1-scripts.js @@ -206,7 +206,13 @@ class TraktorZ1Class { } parameterHandler(field) { - engine.setParameter(field.group, field.name, field.value / 4095); + let value = field.value / 4095; + // Crossfader value don't reach boundaries and need safe margins + // min: 36 - max: 4083 + if (field.name === "crossfader") { + value = (field.value - 36) / 4047; + } + engine.setParameter(field.group, field.name, value); } outputHandler(value, group, key) { From 2a843bc4ce293f68d710384c8f9cf2a4fd67cc12 Mon Sep 17 00:00:00 2001 From: Arthur Vimond Date: Thu, 29 Jan 2026 11:26:20 +0100 Subject: [PATCH 2/4] feat(controllers): apply crossfader calibration values --- res/controllers/Traktor-Kontrol-Z1-scripts.js | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-Z1-scripts.js b/res/controllers/Traktor-Kontrol-Z1-scripts.js index a9c4d6606adb..a9a8024cf025 100644 --- a/res/controllers/Traktor-Kontrol-Z1-scripts.js +++ b/res/controllers/Traktor-Kontrol-Z1-scripts.js @@ -16,11 +16,15 @@ class TraktorZ1Class { this.vuLeftConnection = {}; this.vuRightConnection = {}; this.vuMeterThresholds = {"vu-30": (1 / 7), "vu-15": (2 / 7), "vu-6": (3 / 7), "vu-3": (4 / 7), "vu0": (5 / 7), "vu3": (6 / 7), "vu6": (7 / 7)}; + + this.rawCalibration = {}; + this.calibration = null; } init(_id) { this.id = _id; + this.calibrate(); this.registerInputPackets(); this.registerOutputPackets(); this.readCurrentPosition(); @@ -116,6 +120,32 @@ class TraktorZ1Class { this.lightDeck(false); } + calibrate() { + this.rawCalibration.faders = new Uint8Array(0x20 * 3); + this.rawCalibration.faders.set(new Uint8Array(controller.getFeatureReport(0xD1)), 0x00); + this.rawCalibration.faders.set(new Uint8Array(controller.getFeatureReport(0xD2)), 0x20); + this.rawCalibration.faders.set(new Uint8Array(controller.getFeatureReport(0xD3)), 0x40); + this.calibration = this.parseRawCalibration(); + } + + parseRawCalibration() { + return { + crossfader: this.parseCrossfaderCalibration(0x3C), + }; + } + + parseCrossfaderCalibration(index) { + const data = this.rawCalibration.faders; + return { + min: this.parseUint16Le(data, index), + max: this.parseUint16Le(data, index+2), + }; + } + + parseUint16Le(data, index) { + return data[index] + (data[index+1]<<8); + } + readCurrentPosition() { // Sync on-screen controls with controller knob positions const report0x01 = new Uint8Array(controller.getInputReport(0x01)); @@ -207,10 +237,13 @@ class TraktorZ1Class { parameterHandler(field) { let value = field.value / 4095; - // Crossfader value don't reach boundaries and need safe margins - // min: 36 - max: 4083 + // Crossfader value don't reach boundaries and need to use calibration values + // Also apply extra safe margins + const safeMargins = 5; if (field.name === "crossfader") { - value = (field.value - 36) / 4047; + const min = this.calibration.crossfader.min; + const max = this.calibration.crossfader.max; + value = script.absoluteLin(field.value, 0, 1, min + safeMargins, max - safeMargins); } engine.setParameter(field.group, field.name, value); } From b7f78b8756fb6621c99904f2fb7ddeb4109ad0c6 Mon Sep 17 00:00:00 2001 From: Arthur Vimond Date: Thu, 29 Jan 2026 13:26:40 +0100 Subject: [PATCH 3/4] fix(controllers): add eslint definitions to fix pre-commit error --- res/controllers/Traktor-Kontrol-Z1-scripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/controllers/Traktor-Kontrol-Z1-scripts.js b/res/controllers/Traktor-Kontrol-Z1-scripts.js index a9a8024cf025..20f711fb8f2d 100644 --- a/res/controllers/Traktor-Kontrol-Z1-scripts.js +++ b/res/controllers/Traktor-Kontrol-Z1-scripts.js @@ -5,6 +5,8 @@ // Author: djantti // +// eslint definitions +/* global controller, HIDController, HIDPacket */ class TraktorZ1Class { constructor() { this.controller = new HIDController(); From b7b96e16a989294e37c5f3580629fec9b714d51c Mon Sep 17 00:00:00 2001 From: Arthur Vimond Date: Fri, 30 Jan 2026 10:26:35 +0100 Subject: [PATCH 4/4] refactor(controllers): use separate crossfaderHandler() --- res/controllers/Traktor-Kontrol-Z1-scripts.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/res/controllers/Traktor-Kontrol-Z1-scripts.js b/res/controllers/Traktor-Kontrol-Z1-scripts.js index 20f711fb8f2d..a83a7a34dfb0 100644 --- a/res/controllers/Traktor-Kontrol-Z1-scripts.js +++ b/res/controllers/Traktor-Kontrol-Z1-scripts.js @@ -19,6 +19,7 @@ class TraktorZ1Class { this.vuRightConnection = {}; this.vuMeterThresholds = {"vu-30": (1 / 7), "vu-15": (2 / 7), "vu-6": (3 / 7), "vu-3": (4 / 7), "vu0": (5 / 7), "vu3": (6 / 7), "vu6": (7 / 7)}; + // Calibration data this.rawCalibration = {}; this.calibration = null; } @@ -73,7 +74,7 @@ class TraktorZ1Class { this.registerInputScaler(InputReport0x01, "[Channel2]", "volume", 0x19, 0xFFFF, this.parameterHandler.bind(this)); // Crossfader - this.registerInputScaler(InputReport0x01, "[Master]", "crossfader", 0x1B, 0xFFFF, this.parameterHandler.bind(this)); + this.registerInputScaler(InputReport0x01, "[Master]", "crossfader", 0x1B, 0xFFFF, this.crossfaderHandler.bind(this)); this.controller.registerInputPacket(InputReport0x01); } @@ -238,15 +239,16 @@ class TraktorZ1Class { } parameterHandler(field) { - let value = field.value / 4095; + engine.setParameter(field.group, field.name, field.value / 4095); + } + + crossfaderHandler(field) { // Crossfader value don't reach boundaries and need to use calibration values // Also apply extra safe margins const safeMargins = 5; - if (field.name === "crossfader") { - const min = this.calibration.crossfader.min; - const max = this.calibration.crossfader.max; - value = script.absoluteLin(field.value, 0, 1, min + safeMargins, max - safeMargins); - } + const min = this.calibration.crossfader.min; + const max = this.calibration.crossfader.max; + const value = script.absoluteLin(field.value, 0, 1, min + safeMargins, max - safeMargins); engine.setParameter(field.group, field.name, value); }