diff options
author | josepma <josepma@gmail.com> | 2016-09-22 20:58:04 +0200 |
---|---|---|
committer | josepma <josepma@gmail.com> | 2016-09-22 20:58:04 +0200 |
commit | 1673594801b7a2d3436e16b0dc2d21bb4759c7ba (patch) | |
tree | be849ff7a3088faa95140e615434ac7b7aec2246 /res/controllers/Hercules-DJ-Console-4-Mx-scripts.js | |
parent | ae19720b4f282b9ea3e28e1dd110666165263b6c (diff) |
New version of DJ console 4mx 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 | 2229 |
1 files changed, 1545 insertions, 684 deletions
diff --git a/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js b/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js index 92eeb5933f..e5c66e8765 100644 --- a/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js +++ b/res/controllers/Hercules-DJ-Console-4-Mx-scripts.js @@ -1,684 +1,1545 @@ -///////////////////////////////////////////////////////////////////// -//===================================================== -//_#_ Hercules DJ Console 4-Mx scripts by josepma. _##_ -//_##________ Based partially on the Mk4 script ___###_ -//===================================================== -// 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 range automatically (8bit actually) for the pitch slider if the controller is configured to use it. -// 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: -// ------ -// Check the dedicated controller wiki page at: -// http://mixxx.org/wiki/doku.php/hercules_dj_console_4-mx -// -// Variables on Hercules4Mx.userSettings can be modified by users to suit their preferences. -///////////////////////////////////////////////////////////////////// -var Hercules4Mx = function() {}; - - -// The 4 possible values for the beatFlashLed option below. -Hercules4Mx.Leds = { - "none" : 0, - "syncLed" : 0x11, - "pitchResetLed" : 0x15, - "JogLed" : 0x1A -}; -// --- Personal preferences configuration --- -Hercules4Mx.userSettings = { - // 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 the button 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, - // _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, - // _Scratching_ beta value for the filter (start with alpha/32 and tune from there) - 'beta': (1 / 8) / 32, - // 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 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': 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': null -}; - -Hercules4Mx.scratchEnabled = false; -Hercules4Mx.previousHeadMix = 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]; - -// 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); - - //---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. - // - // ignore jog wheel movement: (codes from 0x7A to 0x7D, one for each deck). - // midi.sendShortMsg(Hercules4Mx.CC, 0x7A, enable); enable = 0 obey movement, enable = 0x7F ignore movement - - // Connect several signals to javascript events, like song load, pre-fader-listen, loops or effects - engine.connectControl("[AutoDJ]","enabled","Hercules4Mx.onAutoDJ"); - engine.connectControl("[AutoDJ]","fade_now","Hercules4Mx.onAutoDJFade"); - 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"); - } - } - 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. The other sliders and knobs have softtakeover set in the xml mapping. - for (i = 1; i <= 4; i++) { - engine.softTakeover("[Channel" + i + "]","rate",true); - engine.softTakeover("[Channel" + i + "]","rate",true); - } -}; -Hercules4Mx.shutdown = function() { - if (Hercules4Mx.navigationStatus.timeoutId !== null) { - engine.stopTimer(Hercules4Mx.navigationStatus.timeoutId); - } - 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 = 0x3C; i <= 0x3F; i++) { //auto, scratch, files, folders - midi.sendShortMsg(Hercules4Mx.NOnC1, i, 0x00); - midi.sendShortMsg(Hercules4Mx.NOnC1, i + 0x40, 0x00); - } - 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); - } - 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); - } - // I've put these on a separate loop so that there are more chances for decks A/B leds to light off when shutdown, - // since there is a strange problem where not all messages are delivered. - for (i = 0x1; i <= 0x11; i++) { // Fx, cue, play, cuesel,stop, sync - 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 = 0x15; i <= 0x1A; i++) { //pitch led, source, kill,jog touch - 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); - } -}; -/////////////////////////////////////////////////////////////////// -// --- 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; - if (engine.getParameter("[AutoDJ]", "enabled") === 0) { - //If we are not in autodj mode - var deck = script.deckFromGroup(group); - for (i = 1; i <= 4; i++) { - //Change headphone cue (pfl) to the deck on which the song loaded. - engine.setParameter("[Channel" + i + "]", "pfl", (deck === i) ? 1 : 0); - } - - var currentHeadMix = engine.getParameter("[Master]", "headMix"); - if (currentHeadMix == 1) { - //Change the headmix if it was to full Mix. - engine.setParameter("[Master]", "headMix", Hercules4Mx.previousHeadMix); - } - } -}; - -//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); - var finalvalue = (value == -1) ? 0 : value; - var deck = script.deckFromGroup(group); - var messageto = (deck === 1 || deck == 2) ? Hercules4Mx.NOnC1 : Hercules4Mx.NOnC2; - var offset = (deck === 1 || deck == 3) ? 0x00 : 0x20; - var b1 = engine.getParameter("[Channel" + deck + "]", "beatloop_0.5_enabled"); - var b2 = engine.getParameter("[Channel" + deck + "]", "beatloop_1_enabled"); - 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, light up buttons 3 and 4 - b3 = (finalvalue) ? 1 : 0; - b4 = b3; - } - midi.sendShortMsg(messageto, 0x01 + offset, b1); - midi.sendShortMsg(messageto, 0x02 + offset, b2); - midi.sendShortMsg(messageto, 0x03 + offset, b3); - midi.sendShortMsg(messageto, 0x04 + offset, b4); -}; - -// Controls the action to do when the headphone cue (pre-fader-listen) buttons are pressed. -Hercules4Mx.onPreFaderListen = function(value, group, control) { - 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"); - var pfl4 = engine.getParameter("[Channel4]", "pfl"); - var currentHeadMix = engine.getParameter("[Master]", "headMix"); - - if (pfl1 === 0 && pfl2 === 0 && pfl3 === 0 && pfl4 === 0) { - // If they are all disabled after switching, move headmix to master. - Hercules4Mx.previousHeadMix = currentHeadMix; - engine.setParameter("[Master]", "headMix", 1); - } else if (currentHeadMix == 1) { - // If at least one is enabled and headmix is set to master, restore previous headmix. - engine.setParameter("[Master]", "headMix", Hercules4Mx.previousHeadMix); - } - } -}; - -//AutoDJ is activated or deactivated. -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 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 !== 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 = 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 - //an option to get the duration of the fading, that's why i simply put there 5 seconds. - Hercules4Mx.autoDJfadingId = engine.beginTimer(5000, "Hercules4Mx.onAutoDJFadeOff", true); -}; -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. -//The virtualDJ function is to do a fade to next in interactive mode (Mixxx fade to next requires autoDJ) -//The would then be determined by the beats per minute. -Hercules4Mx.autoDJButton = function(midichan, control, value) { - if (value) { - if (engine.getParameter("[AutoDJ]", "enabled") === 0) { - //If not enable, enable autoDJ - engine.setParameter("[AutoDJ]", "enabled", 1); - } else { - //If already in autodj, do a crossfade to next track - engine.setParameter("[AutoDJ]", "fade_now", 1); - } - } -}; - -//Stop button is pressed in a deck. -Hercules4Mx.stopButton = function(midichan, control, value, status, group) { - if (value) { - engine.setParameter(group, "cue_gotoandstop", 1); - - var stop1 = engine.getParameter("[Channel1]", "stop"); - var stop2 = engine.getParameter("[Channel2]", "stop"); - var autodj = engine.getParameter("[AutoDJ]", "enabled"); - //Note: autodj only acts on decks 1 and 2, so not checking decks 3 and 4. - if (stop1 && stop2 && autodj) { - //If autoDJ enabled and all decks are stopped. disable autoDJ. - engine.setParameter("[AutoDJ]", "enabled", 0); - } - } -}; - -//Advanced navigation mode. -Hercules4Mx.navigation = function(midichan, control, value, status, group) { - if (value) { - if (control === 0x3E) { - //FILES - 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 = false; - midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3E, 0x7F); - midi.sendShortMsg(Hercules4Mx.NOnC1, 0x3F, 0x00); - } - } else if (control === 0x3F) { - //FOLDERS - if (Hercules4Mx.navigationStatus.sidebar ) { - //if we are already on sidebar, open/close group - engine.setParameter('[Playlist]', 'ToggleSelectedSidebarItem', 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 = true; - Hercules4Mx.doNavigate(); - } else if (control === 0x41) { - //DOWN - Hercules4Mx.navigationStatus.direction = 1; - Hercules4Mx.navigationStatus.enabled = true; - Hercules4Mx.doNavigate(); - } - 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 = false; - if (Hercules4Mx.navigationStatus.timeoutId !== null) { - engine.stopTimer(Hercules4Mx.navigationStatus.timeoutId); - Hercules4Mx.navigationStatus.timeoutId = null; - } - } -}; - -// Internal navigate action. -Hercules4Mx.doNavigate = function() { - if (Hercules4Mx.navigationStatus.sidebar === false) { - if (Hercules4Mx.navigationStatus.direction === 1) { - engine.setParameter("[Playlist]", "SelectNextTrack", "1"); - } else { - engine.setParameter("[Playlist]", "SelectPrevTrack", "1"); - } - } else { - if (Hercules4Mx.navigationStatus.direction === 1) { - engine.setParameter("[Playlist]", "SelectNextPlaylist", "1"); - } else { - engine.setParameter("[Playlist]", "SelectPrevPlaylist", "1"); - } - } -}; -//Any of the shift buttons for effects has been pressed. This button simply changes -//the controller internal state, but we can use it for other reasons while the user maintains it pressed. -Hercules4Mx.pressEffectShift = function(midichan, control, value) { - // I don't diferentiate between decks. I don't expect two shift buttons being pressed at the same time. - Hercules4Mx.shiftPressed = (value) ? true : false; -}; -//Indicator of the shift effect state change. This happens always after shift is released -//We control if we let it change or not -Hercules4Mx.stateEffectShift = function(midichan, control, value, status, group) { - if (Hercules4Mx.shiftUsed) { - //If shift state was changed because of the alternate shift usage, restore its state. - Hercules4Mx.shiftUsed = false; - var deck = script.deckFromGroup(group) - 1; - midi.sendShortMsg(Hercules4Mx.CC, 0x72 + deck, !value); - } -}; - -//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) { - //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. - step = 1 / 127; - //Tell shift button not to change state. - Hercules4Mx.shiftUsed = true; - } - engine.setParameter(group, "super1", engine.getParameter(group, "super1") + step * direction); -}; - -// Any of the FX buttons has been pressed -// There are 6 physical buttons present per deck, and also a "shift" button used by the controller -// itself to switch between messages 1 to 6 and messages 7 to 12, depending if it is enabled or not. -// Since the shift button also sends a message when it is pressed and when it is released, -// I've been able to setup up to 24 different actions per deck. -// I call these additional 12 messages the "shift-pressed" mode. -Hercules4Mx.FXButton = function(midichan, control, value, status, group) { - var deck = script.deckFromGroup(group); - if (Hercules4Mx.shiftPressed) { - //Tell shift not to change state. - Hercules4Mx.shiftUsed = true; - } - switch (control) { - // 1 to 6 and 0x21 to 0x26 are the 6 left deck and right deck buttons respectively, with shift disabled. - // Loop buttons - case 0x01: - case 0x21: // K1, beatloop 1/ Loop in - if (value) { - //beatloop 0.125 in "shift-pressed" mode, beatloop of 0.5 beat otherwise - if (Hercules4Mx.shiftPressed) { - engine.setValue(group, "beatloop_0.125_toggle", 1); - } else { - engine.setValue(group, "beatloop_0.5_toggle", 1); - } - } - break; - case 0x02: - case 0x22: // K2, beatloop 2/ Loop out - if (value) { - //beatlook 0.25 in "shift-pressed" mode, beatloop of 1 beat otherwise - if (Hercules4Mx.shiftPressed) { - engine.setValue(group, "beatloop_0.25_toggle", 1); - } else { - engine.setValue(group, "beatloop_1_toggle", 1); - } - } - break; - case 0x03: - case 0x23: // K3, beatloop 4/ Reloop/Exit - if (value) { - //enable/disable loop in "shift-pressed" mode, beatloop of 2 beat otherwise - if (Hercules4Mx.shiftPressed) { - engine.setValue(group, "reloop_exit", 1); - } else { - engine.setValue(group, "beatloop_2_toggle", 1); - } - } - break; - case 0x04: - case 0x24: // K4, beatloop 8/ Reloop/Exit - if (value) { - //enable/disable loop in "shift-pressed" mode, beatloop of 4 beat otherwise - if (Hercules4Mx.shiftPressed) { - engine.setValue(group, "reloop_exit", 1); - } else { - engine.setValue(group, "beatloop_4_toggle", 1); - } - } - break; - // Reverse play buttons - case 0x05: - case 0x25: // K5, reverse play - engine.setValue(group, "reverse", (value) ? 1 : 0); - break; - case 0x06: - case 0x26: // K6, reverse roll play - engine.setValue(group, "reverseroll", (value) ? 1 : 0); - break; - - // 7 to 0xC and 0x27 to 0x3C are the 6 left deck and right deck buttons respectively, with shift enabled. - // Hotcue buttons: - case 0x07: - case 0x27: // K7 Hotcue 1 activate/ clear - if (Hercules4Mx.shiftPressed) { - if (value) { - engine.setValue(group, "hotcue_1_clear", 1); - } - } else { - engine.setValue(group, "hotcue_1_activate", (value) ? 1 : 0); - } - break; - case 0x08: - case 0x28: // K8 Hotcue 2 activate/ clear - if (Hercules4Mx.shiftPressed) { - if (value) { - engine.setValue(group, "hotcue_2_clear", 1); - } - } else { - engine.setValue(group, "hotcue_2_activate", (value) ? 1 : 0); - } - break; - case 0x09: - case 0x29: // K9 Hotcue 3 activate/ clear - if (Hercules4Mx.shiftPressed) { - if (value) { - engine.setValue(group, "hotcue_3_clear", 1); - } - } else { - engine.setValue(group, "hotcue_3_activate", (value) ? 1 : 0); - } - break; - case 0x0A: - case 0x2A: // K10 Hotcue 4 activate/ clear - if (Hercules4Mx.shiftPressed) { - if (value) { - engine.setValue(group, "hotcue_4_clear", 1); - } - } else { - engine.setValue(group, "hotcue_4_activate", (value) ? 1 : 0); - } - break; - //Effects - case 0x0B: - case 0x2B: // K11. Effect Unit 1 - if (value) { - engine.setParameter("[EffectRack1_EffectUnit1]", "group_[Channel" + deck + "]_enable", !engine.getParameter("[EffectRack1_EffectUnit1]", "group_[Channel" + deck + "]_enable")); - } - break; - case 0x0C: - case 0x2C: // K12. Effect Unit 2 - if (value) { - engine.setParameter("[EffectRack1_EffectUnit2]", "group_[Channel" + deck + "]_enable", !engine.getParameter("[EffectRack1_EffectUnit2]", "group_[Channel" + deck + "]_enable")); - } - break; - } -}; - -//Jog wheel moved without pressure (for seeking, speeding or slowing down, or navigating) -Hercules4Mx.jogWheel = function(midichan, control, value, status, group) { - //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 = null; - } - Hercules4Mx.navigationStatus.direction = direction; - Hercules4Mx.doNavigate(); - } else { - engine.setValue(group, "jog", direction + engine.getValue(group, "jog")); - } -}; - -// The "scratch" button is used to enable or disable scratching on the jog wheels. -// 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.scratchEnabled ) { - Hercules4Mx.scratchEnabled = false; - midi.sendShortMsg(Hercules4Mx.NOnC1, 0x7D, 0x00); - if (Hercules4Mx.userSettings.crossfaderScratchCurve) { - midi.sendShortMsg(Hercules4Mx.CC, 0x7E, 0x00); - } - } else { - 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.scratchEnabled && value) { - // If button down - engine.scratchEnable(script.deckFromGroup(group), - 256 * Hercules4Mx.userSettings.sensitivity, - Hercules4Mx.userSettings.vinylSpeed, - Hercules4Mx.userSettings.alpha, - Hercules4Mx.userSettings.beta); - } else { - // If button up - engine.scratchDisable(script.deckFromGroup(group)); - } -}; -//Jog wheel used with pressure (for scratching) -Hercules4Mx.scratchWheel = function(midichan, control, value, status, group) { - 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 { - //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*0x80; - } - 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]; - Hercules4Mx.pitch14bitMode = true; - engine.setParameter(group, "rate", (msbval+value)/0x3FFF); -}; +/////////////////////////////////////////////////////////////////////
+//=====================================================
+//_#_ Hercules DJ Console 4-Mx scripts by josepma. _##_
+//_##________ Based partially on the Mk4 script ___###_
+//=====================================================
+// 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 range automatically (8bit actually) for the pitch slider if the controller is configured to use it.
+// 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.
+// Version 2016-09-22
+// Beatgrid editing mode enabled with shift+sync. Allows to correct the beatgrid from the controller.
+// (For when you're in the middle of a mix and something is not properly aligned)
+// Brake effect (power unplug) with shift+stop, backward playing moved to shift+play and forward and rewind by beats.
+// Keylock, quantize and master sync (shift pitch scale up, shift pitch scale down and sync pressed for 400ms respectively).
+// Improvements and fixes on sync button and navigation.
+// Corrections in soft takeover, and initialization of control values from their physical positions on Mixxx startup.
+// Audio vu meters on the kill/source buttons that switches between master and decks on pfl. Can be switched
+// off on userSettings. If kill or source buttons are activated, the vu on that channel is deactivated.
+// Reimplemented the actions for Fx buttons. It now allows to have personalized mappings, and comes already with three:
+// Manual/VirtualDJ setup, Mixxx 2.0 setup and a new setup that adds more functionality, like playing 4 samplers.
+// New loop edit mode. It allows for a random length loop as well as more beatloop sizes. It is also possible to modify
+// a loop size with the fx knob. See the updated wiki for a detailed explanation.
+// The FX "super" knob can be controlled from the controller now. Maintain the fx button pressed and move the knob.
+//
+// Usage:
+// ------
+// Check the dedicated controller wiki page at:
+// http://mixxx.org/wiki/doku.php/hercules_dj_console_4-mx
+//
+// Variables on Hercules4Mx.userSettings can be modified by users to suit their preferences.
+/////////////////////////////////////////////////////////////////////
+var Hercules4Mx = function() {};
+
+
+// The 4 possible values for the beatFlashLed option below.
+Hercules4Mx.Leds = {
+ "none": 0,
+ "syncLed": 0x11,
+ "pitchResetLed": 0x15,
+ "JogLed": 0x1A
+};
+// --- Personal preferences configuration ---
+Hercules4Mx.userSettings = {
+ // 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 the button will not show sync master state.
+ 'beatFlashLed': Hercules4Mx.Leds.JogLed,
+ // Simulate vuMeters using the kill and source buttons. If enabled, shows master vus, or deck vu depending if prefader listen button is enabled or not.
+ 'useVuMeters': true,
+ // KeyRepeat speed for navigating up/down, in milliseconds. 100 is a good value. Lower values make it scroll faster.
+ 'naviScrollSpeed': 100,
+ // 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,
+ // _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,
+ // _Scratching_ beta value for the filter (start with alpha/32 and tune from there)
+ 'beta': (1 / 8) / 32,
+ // 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,
+ // This indicates which mapping for the FX buttons should Mixxx use.
+ // The possible values are:
+ // original : As they are in the Hercules Manual and the default setup in Virtual DJ 7 LE.
+ // mixxx20 : As they were initially defined with the release of Mixxx 2.0
+ / |