Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hercules DJControl Jogvision: First release (all MIDI mapped) #2370

Merged
merged 35 commits into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f010f37
Hercules DJControl Jogvision: First release (all MIDI mapped)
Nov 25, 2019
80c2b32
Hercules DJControl Jogvision: reduced and cleaned the size of the Jav…
Dec 2, 2019
f978a96
Hercules DJControl Jogvision: code cleanup and added orange color to
Dec 13, 2019
ea6e6b9
CONTROLLER Hercules_DJControl_Jovision:
Jan 3, 2020
78a4e25
Controller - Hercules DJControl Jogvision:
Jan 16, 2020
e4694b4
Controller: Hercules DJControl Jogvision
Jan 16, 2020
afba702
Controller Herculer DJControl Jogvision: Removed a log trace at shutdown
Feb 5, 2020
2d8fa02
Controller Hercules DJControl Jogvision: fixed a bug ('cause I'm an
Feb 5, 2020
fb9817e
Controller Herculer DJControl Jogvision: removed unused variables
Feb 5, 2020
f50c2ee
Controller Herculer DJControl Jogvision: re-added some vars with an '…
Feb 6, 2020
cc364cb
Because Jan Holthuis tolde me to do it ;P
Feb 6, 2020
3a88b38
Hercules DJControl Jogvision: Auto-Fix eslint issues
Holzhaus Feb 7, 2020
acca731
Hercules DJControl Jogvision: Remove JSHint configuration
Holzhaus Feb 7, 2020
6e254cd
Hercules DJControl Jogvision: Fix use of == instead of ===
Holzhaus Feb 7, 2020
a98cb80
Merge pull request #1 from Holzhaus/Controller_Hercules_DJControl_Jog…
perseo22 Feb 10, 2020
cb3ce6f
Controller Herculer DJControl Jogvision: added varying outer leds
Feb 13, 2020
91c5d99
Controller: Herculer DJControl Jogvision: added backspin effect with jog
May 7, 2020
f80ffef
Controller: Herculer DJControl Jogvision: added latest code style
May 7, 2020
5fe5d09
Controller: Herculer DJControl Kogvision:
May 10, 2020
3052149
fixed beatactive leds from follow to normal
May 10, 2020
e95b8dd
Controller: Hercules DJControl Jogvision - fixed some trailing space,
May 11, 2020
7fdd8f1
Controller: Hercules DJControl Jogvision
May 11, 2020
0813029
Controller: Hercules DJControl Jogvision
May 11, 2020
8eeb41f
Controller: Herculer DJControl Jogvision
May 11, 2020
22e1ba2
Controller: Herculer DJControl Jogvision
May 13, 2020
ec3bb1d
Controller: Herculer DJControl Jogvision
May 13, 2020
acb5e70
- Changed beats led algorithm to match song beats (forward and backwa…
May 18, 2020
ae08776
Controller: Hercules DJControl Jogvision
May 19, 2020
b9d0911
Controller: Herculer DJControl Jogvision
May 19, 2020
dd9a81a
Controller: Hercules DJControl Jogvision
May 20, 2020
a7afb80
Controller: Hercules DJControl Jogvision
May 20, 2020
df030f0
Controller: Hercules DJControl Jogvision
May 20, 2020
fdceeed
Controller: Herculer DJControl Jogvision
Jun 2, 2020
1439c9b
Controller: Hercules DJControl Jogvision
Jun 4, 2020
050bf48
Controller: Hercules DJControl Jogvision
Jun 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
338 changes: 338 additions & 0 deletions res/controllers/Hercules_DJControl_Jogvision-scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,338 @@
// ****************************************************************************
// * Mixxx mapping script file for the Hercules DJControl Jogvision.
// * Author: DJ Phatso, contributions by Kerrick Staley and David TV
// * Version 1.8 (May 2020)
// * Version 1.6 (January 2020)
// * Version 1.5 (January 2020)
// * Version 1.4 (December 2019)
// * Version 1.3 (November 2019)
// * Version 1.2 (November 2019)
// * Version 1.1 (March 2019)
// * Forum: https://www.mixxx.org/forums/viewtopic.php?f=7&t=12580
// * Wiki: https://www.mixxx.org/wiki/doku.php/hercules_dj_control_jogvision
//
// Changes to v1.8
// - Added normal, reverse, blink and follow modes for beat active led (see variable: beatActiveMode)
//
// Changes to v1.7
// - Added back-spin (and forward-spin) effect on "vinyl" mode when jog wheel pushed from top
//
// Changes to v1.6
// - Minor code-style changes (use camelCase, use "double quotes" and other if/else styles)
//
// Changes to v1.5
// - Fixed regression not updating the VuMeters
// - Fixed regression not updating the CUE/MIX buttons
//
// Changes to v1.4
// - Code cleanup and standarization
// - Added "orage" track led color (ala Serato) when play position is beyond the
// part of the track, but before the "end of track" Mixxx signal
//
// Changes to v1.3
// - Enabled the creation of beatloop (beatloopActivate) by using SHIFT+LoopON
// - Changed "LOOP SIZE" to adjust the beatjumpSize (you still can change size
// with surrounding buttons: reloop_toggle key)
// - Added SHIFT+"LOOP SIZE" to move loop left or right by N beats (beatjump)
//
// Changes to v1.2
// - Enabled Jogwheel Outer LED rotation
// - Enabled Beat LEDs
//
// Changes to v1.1
// - Controller knob/slider values are queried on startup, so MIXXX is synced.
// - Fixed vinyl button behavior the first time it"s pressed.
//
// v1.0 : Original release
//
// ****************************************************************************

var on = 0x7F;
var off = 0x00;
var alpha = 1.0 / 8;
var beta = alpha / 16;
var ledRotationSpeed = 60; // The bigger, the slower
var ledRotationTimer = 0;
var masterLeds = 0x90;
var beatActiveMode = "normal"; // normal, reverse, blink, follow
if (beatActiveMode.match(/^(?:normal|reverse)$/g)) {
beatMax = 4;
Holzhaus marked this conversation as resolved.
Show resolved Hide resolved
} else if (beatActiveMode === "blink") {
beatMax = 2;
} else {
beatMax = 8;
}

var DJCJV = {};

DJCJV.vinylModeActive = true;
DJCJV.Channel = [];
DJCJV.Channel["[Channel1]"] = {"central": 0x90, "deck": 0xB0, "beatPosition": 1, "rotation": 0x00, "n": 1};
DJCJV.Channel["[Channel2]"] = {"central": 0x91, "deck": 0xB1, "beatPosition": 1, "rotation": 0x00, "n": 2};

// Initialization
DJCJV.init = function(id) {

print("Hercules DJControl Jogvision id: \""+id+"\" initializing...");
print("Using beatActiveMode="+beatActiveMode+" (beatMax="+beatMax+")");

//Set all LED states to off
midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x7F, off);
midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x7F, off);

// Set Vinyl button LED On.
midi.sendShortMsg(masterLeds, 0x45, on);
DJCJV.vinylModeActive = true;
midi.sendShortMsg(masterLeds, 0x46, on);

// Set Headphone CUE/MIX LED state
if (engine.getValue("[Master]", "headMix") > 0.5) {
midi.sendShortMsg(masterLeds, 0x4C, on); // headset "Mix" button LED
midi.sendShortMsg(masterLeds, 0x4D, off);
} else {
midi.sendShortMsg(masterLeds, 0x4C, off);
midi.sendShortMsg(masterLeds, 0x4D, on); // headset "Cue" button LED
}

//Enable Soft takeover
engine.softTakeover("[Master]", "crossfader", true);
engine.softTakeover("[QuickEffectRack1_[Channel1]]", "super1", true);
engine.softTakeover("[QuickEffectRack1_[Channel2]]", "super1", true);

// Set effects Levels - Dry/Wet - Filters
// Done to work around the limited amount of controls in the Jogvision controller
engine.setParameter("[EffectRack1_EffectUnit1_Effect1]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit1_Effect2]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit1_Effect3]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit2_Effect1]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit2_Effect2]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit2_Effect3]", "meta", 0.6);
engine.setParameter("[EffectRack1_EffectUnit1]", "mix", 0.6);
engine.setParameter("[EffectRack1_EffectUnit2]", "mix", 0.6);
engine.setParameter("[QuickEffectRack1_[Channel1]]", "super1", 0.5);
engine.setParameter("[QuickEffectRack1_[Channel2]]", "super1", 0.5);

// Connect the VUMeters and Jog Inner LED
engine.connectControl("[Channel1]", "VuMeter", "DJCJV.vuMeterUpdate");
engine.connectControl("[Channel2]", "VuMeter", "DJCJV.vuMeterUpdate");
engine.connectControl("[Channel1]", "playposition", "DJCJV.wheelInnerUpdate");
engine.connectControl("[Channel2]", "playposition", "DJCJV.wheelInnerUpdate");

// Connect the beat_active with beat leds
engine.connectControl("[Channel1]", "beat_active", "DJCJV.beatActive");
engine.connectControl("[Channel2]", "beat_active", "DJCJV.beatActive");
engine.connectControl("[Channel1]", "stop", "DJCJV.beatInactive");
engine.connectControl("[Channel2]", "stop", "DJCJV.beatInactive");

// Set inner jog leds to 0
midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x61, 0);
midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x61, 0);
// Set outer jog leds to 0
midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x60, 1);
midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x60, 1);

// Enable jogs' outer leds rotation by timer (when channel is playing)
ledRotationTimer = engine.beginTimer(20, function() {
if (engine.getValue("[Channel1]", "play") === 1) {
midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x60, DJCJV.Channel["[Channel1]"].rotation);
DJCJV.Channel["[Channel1]"].rotation = DJCJV.Channel["[Channel1]"].rotation >= 127 ? 1 : DJCJV.Channel["[Channel1]"].rotation + (engine.getValue("[Channel1]", "bpm") / ledRotationSpeed);
}
if (engine.getValue("[Channel2]", "play") === 1) {
midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x60, DJCJV.Channel["[Channel2]"].rotation);
DJCJV.Channel["[Channel2]"].rotation = DJCJV.Channel["[Channel2]"].rotation >= 127 ? 1 : DJCJV.Channel["[Channel2]"].rotation + (engine.getValue("[Channel2]", "bpm") / ledRotationSpeed);
}
});
Holzhaus marked this conversation as resolved.
Show resolved Hide resolved

// Ask the controller to send all current knob/slider values over MIDI, which will update the corresponding GUI controls in MIXXX.
midi.sendShortMsg(0xB0, 0x7F, on);

print("Hercules DJControl Jogvision id: \""+id+"\" initialized");
};

// Finalization
DJCJV.shutdown = function() {
if (ledRotationTimer) {
engine.stopTimer(ledRotationTimer);
ledRotationTimer = 0;
}
Holzhaus marked this conversation as resolved.
Show resolved Hide resolved
//Set all LED states to off
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Set all LED states to off
// Set all LED states to off

midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x7F, off);
midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x7F, off);
};

// Beat led ACTIVATE (move)
DJCJV.beatActive = function(value, group, _control) {
if (value === 1) {
return;
}
var led = DJCJV.Channel[group].central;
var pos = DJCJV.Channel[group].beatPosition;

Holzhaus marked this conversation as resolved.
Show resolved Hide resolved
// Normal
if (beatActiveMode === "normal") {
midi.sendShortMsg(led, 0x3A, pos === 1 ? on : off);
midi.sendShortMsg(led, 0x3B, pos === 2 ? on : off);
midi.sendShortMsg(led, 0x3C, pos === 3 ? on : off);
midi.sendShortMsg(led, 0x3D, pos === 4 ? on : off);
// Reverse
} else if (beatActiveMode === "reverse") {
midi.sendShortMsg(led, 0x3A, pos !== 1 ? on : off);
midi.sendShortMsg(led, 0x3B, pos !== 2 ? on : off);
midi.sendShortMsg(led, 0x3C, pos !== 3 ? on : off);
midi.sendShortMsg(led, 0x3D, pos !== 4 ? on : off);
// Reverse
} else if (beatActiveMode === "blink") {
midi.sendShortMsg(led, 0x3A, pos === 1 ? on : off);
midi.sendShortMsg(led, 0x3B, pos === 1 ? on : off);
midi.sendShortMsg(led, 0x3C, pos === 1 ? on : off);
midi.sendShortMsg(led, 0x3D, pos === 1 ? on : off);
// Follow
} else if (beatActiveMode === "follow") {
if (pos >= 1) {
midi.sendShortMsg(led, 0x3A, on);
}
if (pos >= 2) {
midi.sendShortMsg(led, 0x3B, on);
}
if (pos >= 3) {
midi.sendShortMsg(led, 0x3C, on);
}
if (pos >= 4) {
midi.sendShortMsg(led, 0x3D, on);
}
if (pos >= 5) {
midi.sendShortMsg(led, 0x3A, off);
}
if (pos >= 6) {
midi.sendShortMsg(led, 0x3B, off);
}
if (pos >= 7) {
midi.sendShortMsg(led, 0x3C, off);
}
if (pos >= 8) {
midi.sendShortMsg(led, 0x3D, off);
}
}

DJCJV.Channel[group].beatPosition = DJCJV.Channel[group].beatPosition >= beatMax ? 1 : DJCJV.Channel[group].beatPosition + 1;
};
// Beat led DEACTIVATE (off all)
DJCJV.beatInactive = function(value, group, _control) {
midi.sendShortMsg(DJCJV.Channel[group].central, 0x3A, off);
midi.sendShortMsg(DJCJV.Channel[group].central, 0x3B, off);
midi.sendShortMsg(DJCJV.Channel[group].central, 0x3C, off);
midi.sendShortMsg(DJCJV.Channel[group].central, 0x3D, off);

DJCJV.Channel[group].beatPosition = 1;
};

//Jogwheels inner LED display - Play position
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Jogwheels inner LED display - Play position
// Jogwheels inner LED display - Play position

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

DJCJV.wheelInnerUpdate = function(value, group, _control) {
var playPos = value * 127;
midi.sendShortMsg(DJCJV.Channel[group].deck, 0x61, playPos);
if (engine.getValue(group, "end_of_track")) {
// Let Mixxx"s engine turn flashing red automatically
return;
} else if (playPos > 64) {
// Turn "track" led to orange if position is beyond the half
midi.sendShortMsg(DJCJV.Channel[group].central, 0x45, 0x02);
} else {
// Turn "track" led to green if position is in the first half
midi.sendShortMsg(DJCJV.Channel[group].central, 0x45, 0x07);
}
};

//Vu Meter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Vu Meter
// Vu Meter

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

DJCJV.vuMeterUpdate = function(value, group, _control) {
midi.sendShortMsg(DJCJV.Channel[group].central, 0x44, value * 6);
};

// Headphone CUE/MIX buttons status
DJCJV.headCue = function(midino, control, value, status, group) {
if (engine.getValue(group, "headMix") === 0) {
engine.setValue(group, "headMix", -1.0);
midi.sendShortMsg(masterLeds, 0x4D, 0x7f);
midi.sendShortMsg(masterLeds, 0x4C, 0x00);
}
};
DJCJV.headMix = function(midino, control, value, status, group) {
if (engine.getValue(group, "headMix") !== 1) {
engine.setValue(group, "headMix", 0);
midi.sendShortMsg(masterLeds, 0x4D, 0x00);
midi.sendShortMsg(masterLeds, 0x4C, 0x7f);
}
};

// Filter (Hercules" AIR FX)
DJCJV.Filter = function(channel, control, value, status, group) {
engine.setValue(group, "super1", 0.5 - value / 255);
};

// Loop section
// SHIFT + Loop ON creates a loop at given point
DJCJV.beatloopActivate = function(channel, control, value, status, group) {
engine.setValue(group, "beatloop_activate", value === 0 ? 0 : 1);
};

// SHIFT+FX(Loop) Knob MOVES the existing loop one beat forward/backward
DJCJV.beatjumpMove = function(channel, control, value, status, group) {
if (value > 64) {
engine.setValue(group, "beatjump_backward", 1);
engine.setValue(group, "beatjump_backward", 0);
} else {
engine.setValue(group, "beatjump_forward", 1);
engine.setValue(group, "beatjump_forward", 0);
}
};
// FX(Loop) Knob changes the AMOUNT of beats to move the loop when requested
DJCJV.beatjumpSize = function(channel, control, value, status, group) {
var currentValue = engine.getValue(group, "beatjumpSize");
if (value > 64) {
engine.setValue(group, "beatjumpSize", currentValue /= 2);
} else {
engine.setValue(group, "beatjumpSize", currentValue *= 2);
}
};

// The Vinyl button, used to enable or disable scratching on the jog wheels.
DJCJV.vinylButton = function(channel, control, value, _status, _group) {
if (!value) {
return;
}

if (DJCJV.vinylModeActive) {
DJCJV.vinylModeActive = false;
midi.sendShortMsg(masterLeds, 0x46, off);
} else {
DJCJV.vinylModeActive = true;
midi.sendShortMsg(masterLeds, 0x46, on);
}
};

// The pressure action over the jog wheel
DJCJV.wheelTouch = function(channel, control, value, status, group) {
if (value > 0 && (engine.getValue(group, "play") !== 1 || DJCJV.vinylModeActive)) {
engine.scratchEnable(DJCJV.Channel[group].n, 400, 33 + 1/3, alpha, beta); // Touching the wheel
} else {
engine.scratchDisable(DJCJV.Channel[group].n); // Released the wheel
}
};

// Using the top of wheel for scratching (Vinyl button On) and bending (Vinyl button Off)
DJCJV.scratchWheel = function(channel, control, value, status, group) {
if (engine.isScratching(DJCJV.Channel[group].n)) {
engine.scratchTick(DJCJV.Channel[group].n, (value >= 64) ? value - 128 : value); // Scratch!
} else {
DJCJV.bendWheel(channel, control, value, status, group); // Pitch bend
}
};

// Bending by either using the side of wheel, or with the Job surface when not in vinyl-mode
DJCJV.bendWheel = function(channel, control, value, status, group) {
//if scratching engaged, do back/forward spin (keep on scratching while jog wheel moves...)
if (engine.isScratching(DJCJV.Channel[group].n)) {
engine.scratchTick(DJCJV.Channel[group].n, (value >= 64) ? -1.5 : 1.5); // back/forward spin
} else {
engine.setValue(group, "jog", (value >= 64) ? value - 128 : value); // Pitch bend
}
};
Loading