diff options
author | josepma <josepma@gmail.com> | 2015-12-20 01:54:53 +0100 |
---|---|---|
committer | josepma <josepma@gmail.com> | 2015-12-20 01:54:53 +0100 |
commit | 7d39837f7cb1066da86fe29964123a3938d075ac (patch) | |
tree | 8b9c2df13b787c0db823af79203a20a65f695609 /res/controllers/Hercules-DJ-Console-4-Mx-scripts.js | |
parent | 9322f8e7f53e8218bf05adad16592fa945227cc0 (diff) |
New update for the Hercules Dj Console 4-Mx mapping
Diffstat (limited to 'res/controllers/Hercules-DJ-Console-4-Mx-scripts.js')
-rw-r--r-- | res/controllers/Hercules-DJ-Console-4-Mx-scripts.js | 427 |
1 files changed, 243 insertions, 184 deletions
diff --git a/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js b/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js index c4bd7a1651..5760f5188c 100644 --- a/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js +++ b/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js @@ -1,230 +1,230 @@ -//////////////////////////////////////////////////////////////////////// -// JSHint configuration // -//////////////////////////////////////////////////////////////////////// -/* global engine */ -/* global script */ -/* global print */ -/* global midi */ -//////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// //===================================================== -//___ Hercules DJ Console 4-Mx scripts by josepma. ____ -//___________ Based partially on the Mk4 script _______ +//_#_ Hercules DJ Console 4-Mx scripts by josepma. _##_ +//_##________ Based partially on the Mk4 script ___###_ //===================================================== -// Version 2015-12-12: Initial version. +// Author: josepma@gmail.com +// +// Version 2015-12-12: +// Initial version. 4 decks, jog wheel and scratch, autodj, navigation and effects. +// Version 2015-12-19: +// Improvements from https://github.com/mixxxdj/mixxx/pull/810 +// Beat flashing can be configurd on pitch reset led, jog led, sync button or disabled completely. +// Option to switch automatically to scratch crossfader curve on scratch mode. +// Soft takeover for pitch, volume faders, eq knobs and gain. +// Use the 14bit (8bit actually) range for the pitch slider if enabled from the configuration. +// Changed stop button to be cue gotoandstop. +// Removed midi channel configuration. It also required modifying the mapping, so it didn't really work. +// Automatically setup some internal values, like 4 decks mode +// Support speed sensor on jog wheel and Fx knob. They need to be moved really fast, so it's rarely useful. // // Usage: // ------ -// Variables on Hercules4Mx.userSettings can be modified by users to suit their preferences. -// -// This mapping and script supports 4 deck mode, jog wheel, scrathing, the whole mixer, -// an improved method of navigation and loops, hotcues and effects. It also has flashing sync button -// following the beats of the song. -// Some options have been modified to do things different than what they were designed for. +// Check the dedicated controller wiki page at: +// http://mixxx.org/wiki/doku.php/hercules_dj_console_4-mx // -// Things you should know: +// Variables on Hercules4Mx.userSettings can be modified by users to suit their preferences. // -// 1) Navigation: -// .Clicking on Files or Folders switches between the library sidebar and the main list. -// .Clicking on Folders when it is already on folders opens/closes the tree branch. -// .Press up or down to navigate. If you keep the button pressed, it will continue in that direction -// .If you press up or down, keep the button pressed and move any of the jog wheels, the navigation -// will follow your wheel movements. You can navigate this way until releasing the up or down key. -// 2) AutoDJ: -// .The "Auto" button is set to work with AutoDJ. In a future release it should be possible to implement -// the auto-crossfade feature that it does in virtualDJ, but it didn't seem necessary for now. -// .If the application is not in autoDJ mode, pressing the Auto button activates the autoDJ mode. -// .If autoDJ mode is activated, Auto button is lit. -// .If you press the AutoDJ button when it is in AutoDJ mode, it starts a fade to next song and button will flash. -// .If in autoDJ mode and pressing the Files button (and already at "Files"), it will skip the next song. -// .AutoDJ mode is deactivated by stopping decks one and two. -// 3) Scratching: -// .In order to be able to scratch, you need to be in scratch mode. That's what the "scratch" button is for. -// .If scratch mode, when moving the jog wheels without pressure it will act normally, and when moved with pressure -// they will scratch. -// 4) Song reproduction: -// .When a song is loaded on a deck and the "autoHeadcueOnLoad" option is set to true, the headphone cue (PFL) will -// automatically switch to that deck, like what Virtual DJ does. This is disabled on AutoDJ. -// .If none of the headphone cue buttons (PFL) is active and autoHeadMix is set to true, the cue/Mix knob -// will be set to full mix so that the mix is heard on headphones. -// .The jog wheels act as usual: when song is stopped they allow fast seeking and when song is playing the speed up or slow down. -// .Pitch sliders act the way it is configured in Mixxx (range and direction) -// .Sync button will be flashing following the beats of the song, like it does in virtualDJ. In a future release this could be optional. -// .Pitch bend buttons sped up or slow down temporarily as configured in Mixxx. -// .Pitch range buttons act as key modifiers. -// .Pitch reset (pressing both pitch range buttons) resets the key. -// .Pitch reset led is lit when key lock is active. In a future version this might change to indicate -// that the key is playing at a different pitch than original, which is what i think Virtual DJ does. -// .Cue and play work as configured in Mixxx. -// .Several controls have the "softtakeover" option enabled, which means that the control will not move in -// the application if the hardware control is far from the position in the application. -// 5) Effects -// .The FX knob in the controller moves the "Fast effect" knob, which is the knob present in the Deck section and -// configurable in the "Equalizer" preferences in Mixxx. In a future version, it could also control the "Superknob" -// of the active effect. -// .If you keep the "shift" button pressed while moving the knob, it will move slowly (more precision). -// .There are 12 effects, 6 with Shift disabled and 6 with Shift enabled. -// .The first four effects are configured to beatloop loops of size 0.5, 1, 2 and 4. They act like the corresponding buttons in Mixxx. -// .If you keep the shift key pressed and press effects 1 and 2, they will set a 0.125 and 0.25th beatloops. -// .When a loop is set that isn't one of these four cases, buttons 3 and 4 will be lit to indicate a loop is present. -// .If you keep the shift key pressed and press either effects 3 or 4, It will act like pressing the loop end/reloop button. -// .The fifth and sixth effects are for reverse play, and reverse and roll. -// .From seventh to tenth, they are the first four hotcues, and act like the buttons in Mixxx (if not set, set. if set, play it) -// .If you keep the shift key pressed and press either of the four hotcue buttons, the hotcue will get cleared. -// .Eleventh and twelveth effects activate the Effects rack 1 and 2 for the specific deck. // -//_____________________________________________________ var Hercules4Mx = function() {}; +Hercules4Mx.Leds = { + "none" : 0, + "syncLed" : 0x11, + "pitchResetLed" : 0x15, + "JogLed" : 0x1A +}; +// --- Personal preferences configuration --- Hercules4Mx.userSettings = { - // --- DJ Console 4MX tray-icon configuration --- - // Midi channel for controls (Tab "advanced") If "1-2", then 0, if "3-4" then 2, if "5-6" then 4... - 'midiChannelOffset': 0, - // Sensitivity (Tab "Main"). Normal means 1/1. You can change the jog wheel sensitivity by either changing this, changing the hercules configuration setting, or both. - 'sensitivity': 1 / 1, - - // --- Personal preferences configuration --- - // Playback speed of the virtual vinyl that is being scratched. 45.00 and 33.33 are the common speeeds. (Lower number equals faster scratch) + // Indicates if the Headphone/Master mix should automatically be set to master when none of the headphone cue buttons are activated. + 'autoHeadMix': false, + // Enable automatically the headphone cue select (PFL) of the deck when a song is loaded. (Like in virtual-dj) + 'autoHeadcueOnLoad': true, + // Flashing at the rythm of the beat on the led. Use the Leds map above. + // Note: if using sync button, then it will not show sync master state. + 'beatFlashLed': Hercules4Mx.Leds.JogLed, + // KeyRepeat speed for navigating up/down, in milliseconds. 125 is a good value. Lower values make it scroll faster. + 'naviScrollSpeed': 125, + // The controller has two modes to report the crossfader position. The default/beatmix curve, and the scratch curve. + // The default curve reports the real position of the control. The scratch curve just crossfades on the edges. + // Setting this setting to true, the curve will change to scratch curve when the scratch mode is on (scratch button). + // Setting it to false will not change it, so it will use the setting configured in the DJHercules Tray-icon configuration. + 'crossfaderScratchCurve' : false, + // _Scratching_ Playback speed of the virtual vinyl that is being scratched. 45.00 and 33.33 are the common speeeds. (Lower number equals faster scratch) 'vinylSpeed': 45, - // alpha value for scratching filter (start with 1/8 (0.125) and tune from there) + // _Scratching_ You should configure this setting to the same value than in the DJHercules tray icon configuration. (Normal means 1/1). + // If crossfaderScratchCurve is true, or the setting is changed while Mixxx is active, this value will be detected automatically. + 'sensitivity': 1 / 1, + // _Scratching_ alpha value for the filter (start with 1/8 (0.125) and tune from there) 'alpha': 1 / 8, - // beta value for scratching filter (start with alpha/32 and tune from there) + // _Scratching_ beta value for the filter (start with alpha/32 and tune from there) 'beta': (1 / 8) / 32, - // Indicates if the Headphone/Master mix should automatically be set to master when none of the headphone cue buttons are pressed. - 'autoHeadMix': false, - // KeyRepeat speed for navigation up/down, in milliseconds. 250 is a good value. Lower values make it scroll faster - 'naviScrollSpeed': 250, - // VirtualDJ-like automatic switching for headphone cue (PFL) on song load - 'autoHeadcueOnLoad': true + // This controls the function of the deck C/deck D buttons (changes the setting in the tray-icon configuration, avanced tab) + // Deck button mode: deckmode=0 2 Decks only, deckmode=1 2 Decks with deck switch button command, deckmode=2 4 decks. + // Since Mixxx supports 4 decks and this mapping is configured for all four decks, the default value is 2. + 'deckButtonMode': 2 }; -/////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// JSHint configuration // +//////////////////////////////////////////////////////////////////////// +/* global engine */ +/* global script */ +/* global print */ +/* global midi */ +//////////////////////////////////////////////////////////////////////// // --- Internal variables ---- Hercules4Mx.debuglog = false; Hercules4Mx.navigationStatus = { - //Navigation direction 1 up, -1 down, 0 undefined + //Navigation direction 1 up, -1 down, 0 do not move 'direction': 0, //Indicator that the up or down buttons are pressed. Separated from direction to avoid a race condition with jogwheel. - 'enabled': 0, - //Indicates if navigating in the sidebar (1) , or in the library (0) - 'sidebar': 0, + 'enabled': false, + //Indicates if navigating in the sidebar, or in the library + 'sidebar': false, //Holds the timeout event id that does the key-repeat action for moving up or down holding only the key. - 'timeoutId': 0 + 'timeoutId': null }; -Hercules4Mx.scratchButton = 0; +Hercules4Mx.scratchEnabled = false; Hercules4Mx.previousHeadMix = 0; -Hercules4Mx.autoDJfadingId = 0; -Hercules4Mx.shiftTimerId = 0; +Hercules4Mx.autoDJfadingId = null; Hercules4Mx.shiftPressed = false; Hercules4Mx.shiftUsed = false; +//Assume 14bit mode is disabled by default, and enable it on the first lsb detected. +Hercules4Mx.pitch14bitMode = false; +Hercules4Mx.pitchMsbValue = [0x40,0x40,0x40,0x40]; -Hercules4Mx.NOnC1 = 0x90 + Hercules4Mx.userSettings.midiChannelOffset; -Hercules4Mx.NOnC2 = 0x91 + Hercules4Mx.userSettings.midiChannelOffset; -Hercules4Mx.CC = 0xB0 + Hercules4Mx.userSettings.midiChannelOffset; +// The Hercules Tray Icon configuration allows to configure a different midi channel for the +// controller. You will need to change all the status codes in the xml mapping and these three +// variables if you use any other than the default of midi channels 1-2. +Hercules4Mx.NOnC1 = 0x90; +Hercules4Mx.NOnC2 = 0x91; +Hercules4Mx.CC = 0xB0; /////////////////////////////////////////////////////////////////// // --- Initialization and shutdown ---- Hercules4Mx.init = function(id, debugging) { Hercules4Mx.debuglog = debugging; + //ensure all leds are in their default state Hercules4Mx.allLedsOff(); + //Activate Files led. + midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3E, 0x7F); + var i; //Shift and deck buttons set to default for (i = 0x72; i <= 0x77; i++) { midi.sendShortMsg(Hercules4Mx.CC, i, 0x00); } + // Deck button mode + midi.sendShortMsg(Hercules4Mx.CC, 0x78, Hercules4Mx.userSettings.deckButtonMode); + // If the crossfader on scratch setting is on, set the value to normal curve by default. + if (Hercules4Mx.userSettings.crossfaderScratchCurve) { + midi.sendShortMsg(Hercules4Mx.CC, 0x7E, 0x00); + } // Tell the controller to report all current values to Mixxx (update_all_controls message) + // Concretely it reports crossfader, master volume, master headmix, and EQ knobs, gain, pitch slider and vol fader of each channel. midi.sendShortMsg(Hercules4Mx.CC, 0x7F, 0x7F); - //Activate Files led. - midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3E, 0x7F); - // Connect song load to onSongLoaded event + //---Other possible actions: + // jog wheel movement sensitivity divisor (i.e. 1/x). + // midi.sendShortMsg(Hercules4Mx.CC, 0x79, sens); sens = 0 most sensitive, 0x7F least sensitive. 0x1 normal, 0x2 1/2, 0x4 1/4, and so on. + // + // lock jog wheel movement: 0x7A to 0x7D for each deck. + // midi.sendShortMsg(Hercules4Mx.CC, 0x7A, enable); enable = 0 not locked, enable = 0x7F locked + + // Connect several signals to javascript events, like song load, pre-fader-listen, looks or effects + for (i = 1; i <= 4; i++) { + engine.connectControl("[Channel" + i + "]", "pfl", "Hercules4Mx.onPreFaderListen"); + engine.connectControl("[Channel" + i + "]", "loop_enabled", "Hercules4Mx.onLoopStateChange"); + engine.connectControl("[Channel" + i + "]", "loop_start_position", "Hercules4Mx.onLoopStateChange"); + engine.connectControl("[Channel" + i + "]", "loop_end_position", "Hercules4Mx.onLoopStateChange"); +// TODO: control when they are enabled, so that FX knob can move the effect unit knob. +// engine.connectControl("[EffectRack1_EffectUnit1]", "group_[Channel" + i + "]_enable", "Hercules4Mx.onEffectStateChange"); +// engine.connectControl("[EffectRack1_EffectUnit2]", "group_[Channel" + i + "]_enable", "Hercules4Mx.onEffectStateChange"); + } if (Hercules4Mx.userSettings.autoHeadcueOnLoad) { for (i = 1; i <= 4; i++) { engine.connectControl("[Channel" + i + "]", "LoadSelectedTrack", "Hercules4Mx.onSongLoaded"); } } - engine.connectControl("[AutoDJ]", "enabled", "Hercules4Mx.onAutoDJ"); - engine.connectControl("[AutoDJ]", "fade_now", "Hercules4Mx.onAutoDJFade"); - engine.trigger("[AutoDJ]", "enabled", "Hercules4Mx.onAutoDJ"); - - engine.connectControl("[Channel1]", "pfl", "Hercules4Mx.onPreFaderListen"); - engine.connectControl("[Channel2]", "pfl", "Hercules4Mx.onPreFaderListen"); - engine.connectControl("[Channel3]", "pfl", "Hercules4Mx.onPreFaderListen"); - engine.connectControl("[Channel4]", "pfl", "Hercules4Mx.onPreFaderListen"); - - engine.connectControl("[Channel1]", "loop_enabled", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel2]", "loop_enabled", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel3]", "loop_enabled", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel4]", "loop_enabled", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel1]", "loop_start_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel2]", "loop_start_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel3]", "loop_start_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel4]", "loop_start_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel1]", "loop_end_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel2]", "loop_end_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel3]", "loop_end_position", "Hercules4Mx.onLoopStateChange"); - engine.connectControl("[Channel4]", "loop_end_position", "Hercules4Mx.onLoopStateChange"); - - engine.connectControl("[EffectRack1_EffectUnit1]", "group_[Channel1]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit1]", "group_[Channel2]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit1]", "group_[Channel3]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit1]", "group_[Channel4]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit2]", "group_[Channel1]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit2]", "group_[Channel2]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit2]", "group_[Channel3]_enable", "Hercules4Mx.onEffectStateChange"); - engine.connectControl("[EffectRack1_EffectUnit2]", "group_[Channel4]_enable", "Hercules4Mx.onEffectStateChange"); + if (Hercules4Mx.userSettings.beatFlashLed !== Hercules4Mx.Leds.syncLed ){ + //Set sync master led indicator + for (i = 1; i <= 4; i++) { + engine.connectControl("[Channel" + i + "]", "sync_enabled", "Hercules4Mx.onSyncLed"); + } + } + if (Hercules4Mx.userSettings.beatFlashLed !== Hercules4Mx.Leds.none) { + //Setup beat flashing led + for (i = 1; i <= 4; i++) { + engine.connectControl("[Channel" + i + "]", "beat_active", "Hercules4Mx.onBeatFlash"); + } + } + + // Activate soft takeover for the rate sliders + for (i = 1; i <= 4; i++) { + engine.softTakeover("[Channel" + i + "]","rate",true); + engine.softTakeover("[Channel" + i + "]","rate",true); + } }; - Hercules4Mx.shutdown = function() { - Hercules4Mx.allLedsOff(); - if (Hercules4Mx.navigationStatus.timeoutId !== 0) { + if (Hercules4Mx.navigationStatus.timeoutId !== null) { engine.stopTimer(Hercules4Mx.navigationStatus.timeoutId); } - if (Hercules4Mx.autoDJfadingId !== 0) { + if (Hercules4Mx.autoDJfadingId !== null) { engine.stopTimer(Hercules4Mx.autoDJfadingId); } + // If the crossfader on scratch setting is on, set the value to normal curve on exit. + if (Hercules4Mx.userSettings.crossfaderScratchCurve) { + midi.sendShortMsg(Hercules4Mx.CC, 0x7E, 0x00); + } + //Cleanup leds before exiting. + Hercules4Mx.allLedsOff(); }; //Set all leds to off Hercules4Mx.allLedsOff = function() { engine.log("Hercules4Mx.allLedsOff: switching leds off"); // Switch off all LEDs + // +0x20 -> the other deck // +0x40 -> blinking. var i; - for (i = 0x1; i <= 0x11; i++) { + for (i = 0x3C; i <= 0x3F; i++) { //auto, scratch, files, folders midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC2, i, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x40, 0x00); - } - for (i = 0x15; i <= 0x1A; i++) { - midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC2, i, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x40, 0x00); } - for (i = 0x21; i <= 0x31; i++) { + for (i = 0x1; i <= 0x11; i++) { // Fx, cue, play, cuesel,stop, sync midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC2, i, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x20, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x20, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x40, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x60, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x60, 0x00); } - for (i = 0x35; i <= 0x3A; i++) { + for (i = 0x15; i <= 0x1A; i++) { //pitch led, source, kill,jog touch midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC2, i, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x20, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x20, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x40, 0x00); - } - for (i = 0x3C; i <= 0x3F; i++) { - midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x60, 0x00); + midi.sendShortMsg(Hercules4Mx.NOnC2, i + 0x60, 0x00); } }; /////////////////////////////////////////////////////////////////// // --- Events ---- +// The jog wheel sensitivity setting has changed. This is reported in two scenarios: +// when the setting is changed in the tray icon, and when the crossfader curve is changed to beatmix. +Hercules4Mx.onSensitivityChange = function(value, group, control) { + Hercules4Mx.userSettings.sensitivity = 1/value; +} + //Action to do when a song is loaded in a deck. virtualDJ automatically enables the headphone cue (PFL) Hercules4Mx.onSongLoaded = function(value, group, control) { var i; @@ -243,6 +243,7 @@ Hercules4Mx.onSongLoaded = function(value, group, control) { } } }; + //A change in the loop position or loop state has happened. Hercules4Mx.onLoopStateChange = function(value, group, control) { engine.log("Hercules4Mx.onLoopStateChange: value, group, control: " + value + ", " + group + ", " + control); @@ -255,7 +256,7 @@ Hercules4Mx.onLoopStateChange = function(value, group, control) { var b3 = engine.getParameter("[Channel" + deck + "]", "beatloop_2_enabled"); var b4 = engine.getParameter("[Channel" + deck + "]", "beatloop_4_enabled"); if (!b1 && !b2 && !b3 && !b4) { - //If no beatloops set but loop is enabled, lit buttons 3 and 4 + //If no beatloops set but loop is enabled, light up buttons 3 and 4 b3 = (finalvalue) ? 1 : 0; b4 = b3; } @@ -267,8 +268,8 @@ Hercules4Mx.onLoopStateChange = function(value, group, control) { // Controls the action to do when the headphone cue (pre-fader-listen) buttons are pressed. Hercules4Mx.onPreFaderListen = function(value, group, control) { - // If automatic head mix to master is enabled, check what to do. if (Hercules4Mx.userSettings.autoHeadMix) { + // If automatic head mix to master is enabled, check what to do. var pfl1 = engine.getParameter("[Channel1]", "pfl"); var pfl2 = engine.getParameter("[Channel2]", "pfl"); var pfl3 = engine.getParameter("[Channel3]", "pfl"); @@ -291,16 +292,16 @@ Hercules4Mx.onAutoDJ = function(value, group, control) { midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3C, (value) ? 0x7F : 0x00); }; -// AutoDJ fade to next is pressed. (seems it isn't called when the fading is done -// automatically by AutoDJ instead of button pressed +// AutoDJ fade to next is pressed. (seems it isn't called when the fading is triggered +// automatically by AutoDJ compared to pressing the button in Mixxx/controller) Hercules4Mx.onAutoDJFade = function(value, group, control) { //Flashing led to indicate fading midi.sendShortMsg(Hercules4Mx.NOnC1, 0x7C, 0x7F); - if (Hercules4Mx.autoDJfadingId !== 0) { + if (Hercules4Mx.autoDJfadingId !== null) { //Ensure the timer is off. //This is a safety measure in case the button is pressed again within the 5 second delay. engine.stopTimer(Hercules4Mx.autoDJfadingId); - Hercules4Mx.autoDJfadingId = 0; + Hercules4Mx.autoDJfadingId = null; } //After 5 seconds, restore non-flashing led. It would be perfect if autoDJFade was triggered also //when the fading ends, but right now it seems this is not possible. Also, it doesn't seem to be @@ -311,6 +312,30 @@ Hercules4Mx.onAutoDJFadeOff = function() { midi.sendShortMsg(Hercules4Mx.NOnC1, 0x7C, 0x00); }; +//Beat flashing changed state +Hercules4Mx.onBeatFlash = function(value, group, control) { + var deck = script.deckFromGroup(group); + var val = (value) ? 0x7F : 0x00; + var led = Hercules4Mx.userSettings.beatFlashLed; + switch(deck){ + case 1: midi.sendShortMsg(Hercules4Mx.NOnC1, led, val); break; + case 2: midi.sendShortMsg(Hercules4Mx.NOnC1, led+0x20, val); break; + case 3: midi.sendShortMsg(Hercules4Mx.NOnC2, led, val); break; + case 4: midi.sendShortMsg(Hercules4Mx.NOnC2, led+0x20, val); break; + } +}; +// Deck's Sync led changed state +Hercules4Mx.onSyncLed = function(value, group, control) { + var deck = script.deckFromGroup(group); + var val = (value) ? 0x7F : 0x00; + switch(deck){ + case 1: midi.sendShortMsg(Hercules4Mx.NOnC1, 0x11, val); break; + case 2: midi.sendShortMsg(Hercules4Mx.NOnC1, 0x31, val); break; + case 3: midi.sendShortMsg(Hercules4Mx.NOnC2, 0x11, val); break; + case 4: midi.sendShortMsg(Hercules4Mx.NOnC2, 0x31, val); break; + } +}; + /////////////////////////////////////////////////////////////////// // --- Actions ---- //Auto DJ button is pressed. Two functions: enable autoDJ, and Fade to next track. @@ -331,7 +356,7 @@ Hercules4Mx.autoDJButton = function(midichan, control, value) { //Stop button is pressed in a deck. Hercules4Mx.stopButton = function(midichan, control, value, status, group) { if (value) { - engine.setParameter(group, "start_stop", 1); + engine.setParameter(group, "cue_gotoandstop", 1); var stop1 = engine.getParameter("[Channel1]", "stop"); var stop2 = engine.getParameter("[Channel2]", "stop"); @@ -349,54 +374,54 @@ Hercules4Mx.navigation = function(midichan, control, value, status, group) { if (value) { if (control === 0x3E) { //FILES - if (Hercules4Mx.navigationStatus.sidebar === 0 && - engine.getParameter("[AutoDJ]", "enabled") === 1) { + if (Hercules4Mx.navigationStatus.sidebar === false && + engine.getParameter("[AutoDJ]", "enabled") === 1) { // if autoDJ enabled and we are already at "files", skip next file engine.setParameter("[AutoDJ]", "skip_next", 1); } else { - Hercules4Mx.navigationStatus.sidebar = 0; + Hercules4Mx.navigationStatus.sidebar = false; midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3E, 0x7F); midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3F, 0x00); } } else if (control === 0x3F) { //FOLDERS - if (Hercules4Mx.navigationStatus.sidebar === 1) { + if (Hercules4Mx.navigationStatus.sidebar ) { //if we are already on sidebar, open/close group engine.setParameter('[Playlist]', 'ToggleSelectedSidebarItem', 1); } - Hercules4Mx.navigationStatus.sidebar = 1; + Hercules4Mx.navigationStatus.sidebar = true; midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3E, 0x00); midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3F, 0x7F); } else if (control === 0x40) { //UP Hercules4Mx.navigationStatus.direction = -1; - Hercules4Mx.navigationStatus.enabled = 1; + Hercules4Mx.navigationStatus.enabled = true; Hercules4Mx.doNavigate(); } else if (control === 0x41) { //DOWN Hercules4Mx.navigationStatus.direction = 1; - Hercules4Mx.navigationStatus.enabled = 1; + Hercules4Mx.navigationStatus.enabled = true; Hercules4Mx.doNavigate(); } - if (Hercules4Mx.navigationStatus.enabled == 1 && - Hercules4Mx.navigationStatus.timeoutId === 0) { + if (Hercules4Mx.navigationStatus.enabled && + Hercules4Mx.navigationStatus.timeoutId === null) { //Enable key-repeat mode. Cursor will continue moving until button is released. Hercules4Mx.navigationStatus.timeoutId = engine.beginTimer(Hercules4Mx.userSettings.naviScrollSpeed, Hercules4Mx.doNavigate); } } else { //On key release disable navigation mode and stop key-repeat. Hercules4Mx.navigationStatus.direction = 0; - Hercules4Mx.navigationStatus.enabled = 0; - if (Hercules4Mx.navigationStatus.timeoutId !== 0) { + Hercules4Mx.navigationStatus.enabled = false; + if (Hercules4Mx.navigationStatus.timeoutId !== null) { engine.stopTimer(Hercules4Mx.navigationStatus.timeoutId); - Hercules4Mx.navigationStatus.timeoutId = 0; + Hercules4Mx.navigationStatus.timeoutId = null; } } }; // Internal navigate action. Hercules4Mx.doNavigate = function() { - if (Hercules4Mx.navigationStatus.sidebar === 0) { + if (Hercules4Mx.navigationStatus.sidebar === false) { if (Hercules4Mx.navigationStatus.direction === 1) { engine.setParameter("[Playlist]", "SelectNextTrack", "1"); } else { @@ -429,7 +454,8 @@ Hercules4Mx.stateEffectShift = function(midichan, control, value, status, group) //The effect knob granularity is very coarse, so we compensate it here so that it behaves like an analog one. Hercules4Mx.effectKnob = function(midichan, control, value, status, group) { - var direction = (value === 0x01) ? 1 : -1; + //It has a speed sensor, but you have to move it really fast for it to send something different. + var direction = (value < 0x40) ? value : value-0x80; var step = 1 / 20; if (Hercules4Mx.shiftPressed) { //If pressing shift, let's move it slowly. @@ -519,7 +545,9 @@ Hercules4Mx.FXButton = function(midichan, control, value, status, group) { if (value) { engine.setValue(group, "hotcue_1_clear", 1); } - } else engine.setValue(group, "hotcue_1_activate", (value) ? 1 : 0); + } else { + engine.setValue(group, "hotcue_1_activate", (value) ? 1 : 0); + } break; case 0x08: case 0x28: // K8 Hotcue 2 activate/ clear @@ -527,7 +555,9 @@ Hercules4Mx.FXButton = function(midichan, control, value, status, group) { if (value) { engine.setValue(group, "hotcue_2_clear", 1); } - } else engine.setValue(group, "hotcue_2_activate", (value) ? 1 : 0); + } else { + engine.setValue(group, "hotcue_2_activate", (value) ? 1 : 0); + } break; case 0x09: case 0x29: // K9 Hotcue 3 activate/ clear @@ -535,7 +565,9 @@ Hercules4Mx.FXButton = function(midichan, control, value, status, group) { if (value) { engine.setValue(group, "hotcue_3_clear", 1); } - } else engine.setValue(group, "hotcue_3_activate", (value) ? 1 : 0); + } else { + engine.setValue(group, "hotcue_3_activate", (value) ? 1 : 0); + } break; case 0x0A: case 0x2A: // K10 Hotcue 4 activate/ clear @@ -543,7 +575,9 @@ Hercules4Mx.FXButton = function(midichan, control, value, status, group) { if (value) { engine.setValue(group, "hotcue_4_clear", 1); } - } else engine.setValue(group, "hotcue_4_activate", (value) ? 1 : 0); + } else { + engine.setValue(group, "hotcue_4_activate", (value) ? 1 : 0); + } break; //Effects case 0x0B: @@ -565,15 +599,15 @@ Hercules4Mx.FXButton = function(midichan, control, value, status, group) { } }; - -//Jog wheel moved without pressure (for speeding or slowing down, or navigating) +//Jog wheel moved without pressure (for seeking, speeding or slowing down, or navigating) Hercules4Mx.jogWheel = function(midichan, control, value, status, group) { - var direction = (value === 0x01) ? 1 : -1; - if (Hercules4Mx.navigationStatus.enabled === 1) { - if (Hercules4Mx.navigationStatus.timeoutId !== 0) { + //It has a speed sensor, but you have to move it really fast for it to send something different. + var direction = (value < 0x40) ? value : value-0x80; + if (Hercules4Mx.navigationStatus.enabled) { + if (Hercules4Mx.navigationStatus.timeoutId !== null) { //Stop key-repeat mode. From now on, obey only jog movement until button is released. engine.stopTimer(Hercules4Mx.navigationStatus.timeoutId); - Hercules4Mx.navigationStatus.timeoutId = 0; + Hercules4Mx.navigationStatus.timeoutId = null; } Hercules4Mx.navigationStatus.direction = direction; Hercules4Mx.doNavigate(); @@ -586,18 +620,24 @@ Hercules4Mx.jogWheel = function(midichan, control, value, status, group) { // Concretely, it tells if it has to ignore or not the pressure sensor in the jog wheel. Hercules4Mx.scratchButton = function(midichan, control, value, status, group) { if (value) { - if (Hercules4Mx.scratchButton === 1) { - Hercules4Mx.scratchButton = 0; + if (Hercules4Mx.scratchEnabled ) { + Hercules4Mx.scratchEnabled = false; midi.sendShortMsg(Hercules4Mx.NOnC1, 0x7D, 0x00); + if (Hercules4Mx.userSettings.crossfaderScratchCurve) { + midi.sendShortMsg(Hercules4Mx.CC, 0x7E, 0x00); + } } else { - Hercules4Mx.scratchButton = 1; + Hercules4Mx.scratchEnabled = true; midi.sendShortMsg(Hercules4Mx.NOnC1, 0x7D, 0x7F); + if (Hercules4Mx.userSettings.crossfaderScratchCurve) { + midi.sendShortMsg(Hercules4Mx.CC, 0x7E, 0x7F); + } } } }; // The pressure action over the jog wheel Hercules4Mx.wheelTouch = function(midichan, control, value, status, group) { - if (Hercules4Mx.scratchButton === 1 && value) { + if (Hercules4Mx.scratchEnabled && value) { // If button down engine.scratchEnable(script.deckFromGroup(group), 256 * Hercules4Mx.userSettings.sensitivity, @@ -611,12 +651,31 @@ Hercules4Mx.wheelTouch = function(midichan, control, value, status, group) { }; //Jog wheel used with pressure (for scratching) Hercules4Mx.scratchWheel = function(midichan, control, value, status, group) { - if (Hercules4Mx.navigationStatus.enabled === 1 || + if (Hercules4Mx.navigationStatus.enabled || !engine.isScratching(script.deckFromGroup(group))) { //If navigating, or not in scratch mode, do jogWheel Hercules4Mx.jogWheel(midichan, control, value, status, group); } else { - var direction = (value === 0x01) ? 1 : -1; + //It has a speed sensor, but you have to move it really fast for it to send something different. + var direction = (value < 0x40) ? value : value-0x80; engine.scratchTick(script.deckFromGroup(group), direction); } }; + +// Pitch slider rate change, MSB (Most significant bits in 14bit mode, or directly the value in 7bit) +Hercules4Mx.rateMsb = function(midichan, control, value, status, group) { + if (Hercules4Mx.pitch14bitMode) { + var deck = script.deckFromGroup(group); + Hercules4Mx.pitchMsbValue[deck-1]=value; + } + else { + engine.setParameter(group, "rate", value/0x7F); + } +}; +// Pitch slider rate change, LSB (Least significant bits in 14bit mode, not called in 7bit) +Hercules4Mx.rateLsb = function(midichan, control, value, status, group) { + var deck = script.deckFromGroup(group); + var msbval = Hercules4Mx.pitchMsbValue[deck-1]*0x80; + Hercules4Mx.pitch14bitMode = true; + engine.setParameter(group, "rate", (msbval+value)/0x3FFF); +}; |