diff --git a/res/controllers/Hercules DJControl Starlight.midi.xml b/res/controllers/Hercules DJControl Starlight.midi.xml new file mode 100644 index 000000000000..3ba160468e5e --- /dev/null +++ b/res/controllers/Hercules DJControl Starlight.midi.xml @@ -0,0 +1,1580 @@ + + + + Hercules DJControl Starlight + DJ Phatso for Hercules Technical Support, contributions by Kerrick Staley + MIDI Preset for Hercules DJControl Starlight + https://mixxx.org/wiki/doku.php/hercules_dj_control_starlight + https://mixxx.org/forums/viewtopic.php?f=7&t=12570 + + + + + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 1 (0x91) + /****************************************************************************************************/ + + // Shift + + [Master] + DJCStarlight.shiftButton + Shift button + 0x90 + 0x03 + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 2 (0x91 Deck A - Standard MODE) + /****************************************************************************************************/ + + // Play + + [Channel1] + play + Play button + 0x91 + 0x07 + + + + + + // CUE + + [Channel1] + cue_default + Cue button + 0x91 + 0x06 + + + + + + // Sync + + [Channel1] + sync_enabled + Sync button + 0x91 + 0x05 + + + + + + // PFL + + [Channel1] + pfl + PFL button + 0x91 + 0x0C + + + + + + // Vinyl button + + [Master] + DJCStarlight.vinylButton + Vinyl + 0x91 + 0x03 + + + + + + // Jog wheel touch + + [Channel1] + DJCStarlight.wheelTouch + Jog Wheel Touch Deck A + 0x91 + 0x08 + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 3 (0x92 Deck B - Standard MODE) + /****************************************************************************************************/ + + // Play + + [Channel2] + play + Play button + 0x92 + 0x07 + + + + + + // CUE + + [Channel2] + cue_default + Cue button + 0x92 + 0x06 + + + + + + // Sync + + [Channel2] + sync_enabled + Sync button + 0x92 + 0x05 + + + + + + // PFL + + [Channel2] + pfl + PFL button + 0x92 + 0x0C + + + + + + // Jog wheel touch + + [Channel2] + DJCStarlight.wheelTouch + Jog Wheel Touch Deck B + 0x92 + 0x08 + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 5 (0x94 Deck A - SHIFT MODE) + /****************************************************************************************************/ + + // Play + + [Channel1] + play_stutter + SHIFT + Play: Play Stutter + 0x94 + 0x07 + + + + + + // CUE + + [Channel1] + start + SHIFT + Cue: REWIND to beginning + 0x94 + 0x06 + + + + + + // Sync + + [Channel1] + sync_master + SHIFT + Sync: Sync Master + 0x94 + 0x05 + + + + + + // PFL + + [Master] + DJCStarlight.cueMaster + CUE Master + 0x94 + 0x0C + + + + + + // Jog wheel touch + + [Channel1] + DJCStarlight.wheelTouchShift + Jog Wheel Shift Touch Deck A + 0x94 + 0x08 + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 6 (0x95 Deck B - SHIFT MODE) + /****************************************************************************************************/ + + // Play + + [Channel2] + play_stutter + SHIFT + Play: Play Stutter + 0x95 + 0x07 + + + + + + // CUE + + [Channel2] + start + SHIFT + Cue: REWIND to beginning + 0x95 + 0x06 + + + + + + // Sync + + [Channel2] + sync_master + SHIFT + Sync: Sync Master + 0x95 + 0x05 + + + + + + // PFL + + [Master] + DJCStarlight.cueMix + Headphone CUE + MIX + 0x95 + 0x0C + + + + + + // Jog wheel touch + + [Channel2] + DJCStarlight.wheelTouchShift + Jog Wheel Shift Touch Deck B + 0x95 + 0x08 + + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 7 (0x96 Deck A - Pads) + /****************************************************************************************************/ + + // Hot Cues (SET) + + [Channel1] + hotcue_1_activate + PAD 1 + 0x96 + 0x00 + + + + + + + [Channel1] + hotcue_2_activate + PAD 2 + 0x96 + 0x01 + + + + + + + [Channel1] + hotcue_3_activate + PAD 3 + 0x96 + 0x02 + + + + + + + [Channel1] + hotcue_4_activate + PAD 4 + 0x96 + 0x03 + + + + + + // Hot-Cue buttons (SHIFT mode) + + [Channel1] + hotcue_1_clear + PAD 1 + 0x96 + 0x08 + + + + + + + [Channel1] + hotcue_2_clear + PAD 2 + 0x96 + 0x09 + + + + + + + [Channel1] + hotcue_3_clear + PAD 3 + 0x96 + 0x0A + + + + + + + [Channel1] + hotcue_4_clear + PAD 4 + 0x96 + 0x0B + + + + + + // LOOP + + [Channel1] + beatloop_1_toggle + Loop 1 Beat (Pad 1) + 0x96 + 0x10 + + + + + + + [Channel1] + beatloop_2_toggle + Loop 2 Beat (Pad 2) + 0x96 + 0x11 + + + + + + + [Channel1] + beatloop_4_toggle + Loop 4 Beat (Pad 3) + 0x96 + 0x12 + + + + + + + [Channel1] + beatloop_8_toggle + Loop 8 Beat (Pad 4) + 0x96 + 0x13 + + + + + + // FX + + [EffectRack1_EffectUnit1_Effect1] + enabled + (Pad 1) + 0x96 + 0x20 + + + + + + + [EffectRack1_EffectUnit1_Effect2] + enabled + (Pad 2) + 0x96 + 0x21 + + + + + + + [EffectRack1_EffectUnit1_Effect3] + enabled + (Pad 3) + 0x96 + 0x22 + + + + + + + [EffectRack1_EffectUnit1] + group_[Channel1]_enable + (Pad 4) + 0x96 + 0x23 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + effect_selector + SHIFT + (Pad 1) + 0x96 + 0x28 + + + + + + + [EffectRack1_EffectUnit1_Effect2] + effect_selector + SHIFT + (Pad 2) + 0x96 + 0x29 + + + + + + + [EffectRack1_EffectUnit1_Effect3] + effect_selector + SHIFT + (Pad 3) + 0x96 + 0x2A + + + + + + // Sampler + + [Sampler1] + cue_gotoandplay + PAD 1 + 0x96 + 0x30 + + + + + + + [Sampler2] + cue_gotoandplay + PAD 2 + 0x96 + 0x31 + + + + + + + [Sampler3] + cue_gotoandplay + PAD 3 + 0x96 + 0x32 + + + + + + + [Sampler4] + cue_gotoandplay + PAD 4 + 0x96 + 0x33 + + + + + + /****************************************************************************************************/ + // NN's MIDI Channel 8 (0x97 Deck B - Pads) + /****************************************************************************************************/ + + // Hot Cues (SET) + + [Channel2] + hotcue_1_activate + PAD 1 + 0x97 + 0x00 + + + + + + + [Channel2] + hotcue_2_activate + PAD 2 + 0x97 + 0x01 + + + + + + + [Channel2] + hotcue_3_activate + PAD 3 + 0x97 + 0x02 + + + + + + + [Channel2] + hotcue_4_activate + PAD 4 + 0x97 + 0x03 + + + + + + // Hot-Cue buttons (SHIFT mode) + + [Channel2] + hotcue_1_clear + PAD 1 + 0x97 + 0x08 + + + + + + + [Channel2] + hotcue_2_clear + PAD 2 + 0x97 + 0x09 + + + + + + + [Channel2] + hotcue_3_clear + PAD 3 + 0x97 + 0x0A + + + + + + + [Channel2] + hotcue_4_clear + PAD 4 + 0x97 + 0x0B + + + + + + // LOOP + + [Channel2] + beatloop_1_toggle + Loop 1 Beat (Pad 1) + 0x97 + 0x10 + + + + + + + [Channel2] + beatloop_2_toggle + Loop 2 Beat (Pad 2) + 0x97 + 0x11 + + + + + + + [Channel2] + beatloop_4_toggle + Loop 4 Beat (Pad 3) + 0x97 + 0x12 + + + + + + + [Channel2] + beatloop_8_toggle + Loop 8 Beat (Pad 4) + 0x97 + 0x13 + + + + + + // FX + + [EffectRack1_EffectUnit2_Effect1] + enabled + (Pad 1) + 0x97 + 0x20 + + + + + + + [EffectRack1_EffectUnit2_Effect2] + enabled + (Pad 2) + 0x97 + 0x21 + + + + + + + [EffectRack1_EffectUnit2_Effect3] + enabled + (Pad 3) + 0x97 + 0x22 + + + + + + + [EffectRack1_EffectUnit2] + group_[Channel2]_enable + (Pad 4) + 0x97 + 0x23 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + effect_selector + SHIFT +(Pad 1) + 0x97 + 0x28 + + + + + + + [EffectRack1_EffectUnit2_Effect2] + effect_selector + SHIFT +(Pad 2) + 0x97 + 0x29 + + + + + + + [EffectRack1_EffectUnit2_Effect3] + effect_selector + SHIFT +(Pad 3) + 0x97 + 0x2A + + + + + + // Sampler + + [Sampler5] + cue_gotoandplay + PAD 1 + 0x97 + 0x30 + + + + + + + [Sampler6] + cue_gotoandplay + PAD 2 + 0x97 + 0x31 + + + + + + + [Sampler7] + cue_gotoandplay + PAD 3 + 0x97 + 0x32 + + + + + + + [Sampler8] + cue_gotoandplay + PAD 4 + 0x97 + 0x33 + + + + + + /****************************************************************************************************/ + // CC's MIDI Channel 1 (0xB0 Standard mode) + /***************************************************************************************************/ + + // Crossfader + + [Master] + crossfader + Crossfader + 0xB0 + 0x00 + + + + + + /****************************************************************************************************/ + // CC's MIDI Channel 2 (0xB1 Deck A - Standard mode) + /***************************************************************************************************/ + + + // Volume + + [Channel1] + volume + Volume Deck A + 0xB1 + 0x00 + + + + + + // EQ + + [EqualizerRack1_[Channel1]_Effect1] + parameter1 + EQ LOW Deck A + 0xB1 + 0x02 + + + + + + // Filter + + [QuickEffectRack1_[Channel1]] + super1 + Filter Deck A + 0xB1 + 0x01 + + + + + + // Pitch slider + + [Channel1] + rate + 0xB1 + 0x08 + + + + + + + + [Channel1] + rate + 0xB1 + 0x28 + + + + + + + // Jog wheel + + [Channel1] + DJCStarlight.scratchWheel + Jog-Wheel Scratch (Held down) + 0xB1 + 0x0A + + + + + + + [Channel1] + DJCStarlight.scratchWheelShift + Jog-Wheel Seek (Held down + Shift) + 0xB4 + 0x0A + + + + + + + [Channel1] + DJCStarlight.bendWheel + Jog-Wheel Pitch Bend + 0xB1 + 0x09 + + + + + + /****************************************************************************************************/ + // CC's MIDI Channel 3 (0xB2 Deck B - Standard mode) + /***************************************************************************************************/ + + // Volume + + [Channel2] + volume + Volume Deck A + 0xB2 + 0x00 + + + + + + // EQ + + [EqualizerRack1_[Channel2]_Effect1] + parameter1 + EQ LOW Deck B + 0xB2 + 0x02 + + + + + + // Filter + + [QuickEffectRack1_[Channel2]] + super1 + Filter Deck A + 0xB2 + 0x01 + + + + + + // Pitch slider + + [Channel2] + rate + 0xB2 + 0x08 + + + + + + + + [Channel2] + rate + 0xB2 + 0x28 + + + + + + + // Jog wheel + + [Channel2] + DJCStarlight.scratchWheel + Jog-Wheel Scratch (Held down) + 0xB2 + 0x0A + + + + + + + [Channel1] + DJCStarlight.scratchWheelShift + Jog-Wheel Seek (Held down + Shift) + 0xB5 + 0x0A + + + + + + + [Channel2] + DJCStarlight.bendWheel + Jog-Wheel Pitch Bend + 0xB2 + 0x09 + + + + + + + + /****************************************************************************************************/ + //LED output + /***************************************************************************************************/ + + + + // LED Transport + + [Channel1] + play_indicator + PLAY LED Deck A + 0.5 + 1 + 0x91 + 0x07 + 0x7f + 0x0 + + + + [Channel1] + cue_indicator + CUE LED Deck A + 0.5 + 1 + 0x91 + 0x06 + 0x7f + 0x0 + + + + [Channel1] + sync_enabled + SYNC LED Deck A + 0.5 + 1 + 0x91 + 0x05 + 0x7f + 0x0 + + + + [Channel1] + sync_master + SYNC LED Deck A(SHIFT mode) + 0.5 + 1 + 0x93 + 0x05 + 0x7f + 0x0 + + + + [Channel2] + play_indicator + PLAY LED Deck B + 0.5 + 1 + 0x92 + 0x07 + 0x7f + 0x0 + + + + [Channel2] + cue_indicator + PLAY LED Deck B + 0.5 + 1 + 0x92 + 0x06 + 0x7f + 0x0 + + + + [Channel2] + sync_enabled + SYNC LED Deck B + 0.5 + 1 + 0x92 + 0x05 + 0x7f + 0x0 + + + + [Channel2] + sync_master + SYNC LED Deck B(SHIFT mode) + 0.5 + 1 + 0x94 + 0x05 + 0x7f + 0x0 + + + + // LED PFL buttons + + [Channel1] + pfl + PFL LED DECK A + 0.5 + 1 + 0x91 + 0x0C + 0x7f + 0x0 + + + + [Channel2] + pfl + PFL LED DECK B + 0.5 + 1 + 0x92 + 0x0C + 0x7f + 0x0 + + + // LED HOT CUE (Normal Mode) + + [Channel1] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x96 + 0x00 + 0x7E + 0.5 + + + + [Channel1] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x96 + 0x01 + 0x7E + 0.5 + + + + [Channel1] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x96 + 0x02 + 0x7E + 0.5 + + + + [Channel1] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x96 + 0x03 + 0x7E + 0.5 + + + + + [Channel2] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x97 + 0x00 + 0x7E + 0.5 + + + + [Channel2] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x97 + 0x01 + 0x7E + 0.5 + + + + [Channel2] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x97 + 0x02 + 0x7E + 0.5 + + + + [Channel2] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x97 + 0x03 + 0x7E + 0.5 + + + // LED HOT CUE (SHIFT Mode) + + [Channel1] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x96 + 0x08 + 0x7E + 0.5 + + + + [Channel1] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x96 + 0x09 + 0x7E + 0.5 + + + + [Channel1] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x96 + 0x0A + 0x7E + 0.5 + + + + [Channel1] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x96 + 0x0B + 0x7E + 0.5 + + + + + [Channel2] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x97 + 0x08 + 0x7E + 0.5 + + + + [Channel2] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x97 + 0x09 + 0x7E + 0.5 + + + + [Channel2] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x97 + 0x0A + 0x7E + 0.5 + + + + [Channel2] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x97 + 0x0B + 0x7E + 0.5 + + + // LED LOOP + + [Channel1] + beatloop_1_enabled + Loop 1 Beat (Pad 1) + 0x96 + 0x10 + 0x7F + 0.5 + + + + [Channel1] + beatloop_2_enabled + Loop 2 Beat (Pad 2) + 0x96 + 0x11 + 0x7F + 0.5 + + + + [Channel1] + beatloop_4_enabled + Loop 4 Beat (Pad 3) + 0x96 + 0x12 + 0x7F + 0.5 + + + + [Channel1] + beatloop_8_enabled + Loop 8 Beat (Pad 4) + 0x96 + 0x13 + 0x7F + 0.5 + + + + + [Channel2] + beatloop_1_enabled + Loop 1 Beat (Pad 1) + 0x97 + 0x10 + 0x7F + 0.5 + + + + [Channel2] + beatloop_2_enabled + Loop 2 Beat (Pad 2) + 0x97 + 0x11 + 0x7F + 0.5 + + + + [Channel2] + beatloop_4_enabled + Loop 4 Beat (Pad 3) + 0x97 + 0x12 + 0x7F + 0.5 + + + + [Channel2] + beatloop_8_enabled + Loop 8 Beat (Pad 4) + 0x97 + 0x13 + 0x7F + 0.5 + + + + // FX + + [EffectRack1_EffectUnit1_Effect1] + enabled + (Pad 1) + 0x96 + 0x20 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit1_Effect2] + enabled + (Pad 2) + 0x96 + 0x21 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit1_Effect3] + enabled + (Pad 3) + 0x96 + 0x22 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit1] + group_[Channel1]_enable + (Pad 4) + 0x96 + 0x23 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit2_Effect1] + enabled + (Pad 1) + 0x97 + 0x20 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit2_Effect2] + enabled + (Pad 2) + 0x97 + 0x21 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit2_Effect3] + enabled + (Pad 3) + 0x97 + 0x22 + 0x7F + 0.5 + + + + [EffectRack1_EffectUnit2] + group_[Channel2]_enable + (Pad 4) + 0x97 + 0x23 + 0x7F + 0.5 + + + // LED SAMPLE + + [Sampler1] + play_indicator + (Pad 1 DECK A) + 0x96 + 0x30 + 0x7F + 0.5 + + + + [Sampler2] + play_indicator + (Pad 2 DECK A) + 0x96 + 0x31 + 0x7F + 0.5 + + + + [Sampler3] + play_indicator + (Pad 3 DECK A) + 0x96 + 0x32 + 0x7F + 0.5 + + + + [Sampler4] + play_indicator + (Pad 4 DECK A) + 0x96 + 0x33 + 0x7F + 0.5 + + + + [Sampler5] + play_indicator + (Pad 1 DECK B) + 0x97 + 0x30 + 0x7F + 0.5 + + + + [Sampler6] + play_indicator + (Pad 2 DECK B) + 0x97 + 0x31 + 0x7F + 0.5 + + + + [Sampler7] + play_indicator + (Pad 3 DECK B) + 0x97 + 0x32 + 0x7F + 0.5 + + + + [Sampler8] + play_indicator + (Pad 4 DECK B) + 0x97 + 0x33 + 0x7F + 0.5 + + + + + diff --git a/res/controllers/Hercules-DJControl-Starlight-scripts.js b/res/controllers/Hercules-DJControl-Starlight-scripts.js new file mode 100644 index 000000000000..7174e8d2da43 --- /dev/null +++ b/res/controllers/Hercules-DJControl-Starlight-scripts.js @@ -0,0 +1,282 @@ +var DJCStarlight = {}; +/////////////////////////////////////////////////////////////// +// USER OPTIONS // +/////////////////////////////////////////////////////////////// + +// How fast scratching is. +DJCStarlight.scratchScale = 1.0; + +// How much faster seeking (shift+scratch) is than scratching. +DJCStarlight.scratchShiftMultiplier = 4; + +// How fast bending is. +DJCStarlight.bendScale = 1.0; + +// DJControl_Starlight_scripts.js +// +// **************************************************************************** +// * Mixxx mapping script file for the Hercules DJControl Starlight. +// * Author: DJ Phatso and Kerrick Staley +// * Version 1.3 (March 21 2019) +// * Forum: https://mixxx.org/forums/viewtopic.php?f=7&t=12570 +// * Wiki: https://mixxx.org/wiki/doku.php/hercules_dj_control_starlight +// Changes to v1.3 +// - Fix seek-to-start and cue-master behavior. +// - Change loops to 1/2/4/8 beats. +// - Tweak scratch, seek, and bend behavior. +// - Refactor to reduce code size. +// Changes to v1.2 +// - Controller knob/slider values are queried on startup, so MIXXX is synced. +// - Fixed vinyl button behavior the first time it's pressed. +// Changes to v1.1 +// - Vinyl button now enables/disables scratch function (On by default); +// - FX: SHIFT + Pad = Effect Select +// +// v1.0 : Original release + +// TODO: Functions that could be implemented to the script: +// * Tweak/map base LED to other functions (if possible). +// * FX: +// - Potentially pre-select/load effects into deck and set parameters +// * Fix behavior when adjusting tempo slider after pressing [Sync] (tempo +// adjustment should be relative, not absolute). +// **************************************************************************** + +// We have to disable the no-unused-vars check because we have many MIDI +// callbacks that receive a fixed list of arguments, but we usually don't use +// most of these arguments. Eslint seems to make it relatively difficult to +// disable this check on a case-by-case basis, so we disable it for the whole +// file. +// See this GitHub issue for more context: +// https://github.com/eslint/eslint/issues/1939 +/*eslint-disable no-unused-vars*/ + +DJCStarlight.kScratchActionNone = 0; +DJCStarlight.kScratchActionScratch = 1; +DJCStarlight.kScratchActionSeek = 2; +DJCStarlight.kScratchActionBend = 3; + + +// The base LED are mapped to the VU Meter for light show. +DJCStarlight.baseLEDUpdate = function(value, group, control){ + value = (value*127); + switch(control) { + case "VuMeterL": + midi.sendShortMsg(0x91, 0x23, value); + break; + + case "VuMeterR": + midi.sendShortMsg(0x92, 0x23, value); + break; + } +}; + + +DJCStarlight.init = function() { + DJCStarlight.scratchButtonState = true; + DJCStarlight.scratchAction = { + 1: DJCStarlight.kScratchActionNone, + 2: DJCStarlight.kScratchActionNone}; + + // Turn off base LED default behavior + midi.sendShortMsg(0x90,0x24,0x00); + + // Vinyl button LED On. + midi.sendShortMsg(0x91, 0x03, 0x7F); + + // Connect the base LEDs + engine.connectControl("[Channel1]","VuMeterL","DJCStarlight.baseLEDUpdate"); + engine.connectControl("[Channel2]","VuMeterR","DJCStarlight.baseLEDUpdate"); + + // Set effects Levels - Dry/Wet + 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", 1); + engine.setParameter("[EffectRack1_EffectUnit2]", "mix", 1); + + // 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, 0x7F); +}; + + +// The Vinyl button, used to enable or disable scratching on the jog wheels (The Vinyl button enables both deck). +DJCStarlight.vinylButton = function(channel, control, value, status, group) { + if (value) { + if (DJCStarlight.scratchButtonState) { + DJCStarlight.scratchButtonState = false; + midi.sendShortMsg(0x91,0x03,0x00); + + } else { + DJCStarlight.scratchButtonState = true; + midi.sendShortMsg(0x91,0x03,0x7F); + } + } +}; + + +DJCStarlight._scratchEnable = function(deck) { + var alpha = 1.0/8; + var beta = alpha/32; + engine.scratchEnable(deck, 248, 33 + 1/3, alpha, beta); +}; + + +DJCStarlight._convertWheelRotation = function(value) { + // When you rotate the jogwheel, the controller always sends either 0x1 + // (clockwise) or 0x7F (counter clockwise). 0x1 should map to 1, 0x7F + // should map to -1 (IOW it's 7-bit signed). + return value < 0x40 ? 1 : -1; +} + + +// The touch action on the jog wheel's top surface +DJCStarlight.wheelTouch = function(channel, control, value, status, group) { + var deck = channel; + if (value > 0) { + // Touching the wheel. + if (engine.getValue("[Channel" + deck + "]", "play") !== 1 || DJCStarlight.scratchButtonState) { + DJCStarlight._scratchEnable(deck); + DJCStarlight.scratchAction[deck] = DJCStarlight.kScratchActionScratch; + } else { + DJCStarlight.scratchAction[deck] = DJCStarlight.kScratchActionBend; + } + } else { + // Released the wheel. + engine.scratchDisable(deck); + DJCStarlight.scratchAction[deck] = DJCStarlight.kScratchActionNone; + } +}; + + +// The touch action on the jog wheel's top surface while holding shift +DJCStarlight.wheelTouchShift = function(channel, control, value, status, group) { + var deck = channel - 3; + // We always enable scratching regardless of button state. + if (value > 0) { + DJCStarlight._scratchEnable(deck); + DJCStarlight.scratchAction[deck] = DJCStarlight.kScratchActionSeek; + } else { + // Released the wheel. + engine.scratchDisable(deck); + DJCStarlight.scratchAction[deck] = DJCStarlight.kScratchActionNone; + } +}; + + +// Scratching on the jog wheel (rotating it while pressing the top surface) +DJCStarlight._scratchWheelImpl = function(deck, value) { + var interval = DJCStarlight._convertWheelRotation(value); + var scratchAction = DJCStarlight.scratchAction[deck]; + + if (scratchAction == DJCStarlight.kScratchActionScratch) { + engine.scratchTick(deck, interval * DJCStarlight.scratchScale); + } else if (scratchAction == DJCStarlight.kScratchActionSeek) { + engine.scratchTick(deck, + interval + * DJCStarlight.scratchScale + * DJCStarlight.scratchShiftMultiplier); + } else { + DJCStarlight._bendWheelImpl(deck, value); + } +}; + + +// Scratching on the jog wheel (rotating it while pressing the top surface) +DJCStarlight.scratchWheel = function(channel, control, value, status, group) { + var deck = channel; + DJCStarlight._scratchWheelImpl(deck, value); +}; + + +// Seeking on the jog wheel (rotating it while pressing the top surface and holding Shift) +DJCStarlight.scratchWheelShift = function(channel, control, value, status, group) { + var deck = channel - 3; + DJCStarlight._scratchWheelImpl(deck, value); +}; + + +DJCStarlight._bendWheelImpl = function(deck, value) { + var interval = DJCStarlight._convertWheelRotation(value); + engine.setValue('[Channel' + deck + ']', 'jog', + interval * DJCStarlight.bendScale); +}; + + +// Bending on the jog wheel (rotating using the edge) +DJCStarlight.bendWheel = function(channel, control, value, status, group) { + var deck = channel; + DJCStarlight._bendWheelImpl(deck, value); +}; + + +// Cue master button +DJCStarlight.cueMaster = function(channel, control, value, status, group) { + // This button acts as a toggle. Ignore the release. + if (value === 0) { + return; + } + + var masterIsCued = engine.getValue('[Master]', 'headMix') > 0; + // Toggle state. + masterIsCued = !masterIsCued; + + var headMixValue = masterIsCued ? 1 : -1; + engine.setValue('[Master]', 'headMix', headMixValue); + + // Set LED (will be overwritten when [Shift] is released) + var cueMasterLedValue = masterIsCued ? 0x7F : 0x00; + midi.sendShortMsg(0x91, 0x0C, cueMasterLedValue); +}; + + +// Cue mix button, toggles PFL / master split feature +// We need a special function for this because we want to turn on the LED (but +// we *don't* want to turn on the LED when the user clicks the headSplit button +// in the GUI). +DJCStarlight.cueMix = function(channel, control, value, status, group) { + // This button acts as a toggle. Ignore the release. + if (value === 0) { + return; + } + + // Toggle state. + script.toggleControl('[Master]', 'headSplit'); + + // Set LED (will be overwritten when [Shift] is released) + var cueMixLedValue = + engine.getValue('[Master]', 'headSplit') ? 0x7F : 0x00; + midi.sendShortMsg(0x92, 0x0C, cueMixLedValue); +}; + + +DJCStarlight.shiftButton = function(channel, control, value, status, group) { + if (value >= 0x40) { + // When Shift is held, light the LEDS to show the status of the alt + // functions of the cue buttons. + var cueMasterLedValue = + engine.getValue('[Master]', 'headMix') > 0 ? 0x7F : 0x00; + midi.sendShortMsg(0x91, 0x0C, cueMasterLedValue); + var cueMixLedValue = + engine.getValue('[Master]', 'headSplit') ? 0x7F : 0x00; + midi.sendShortMsg(0x92, 0x0C, cueMixLedValue); + } else { + // When Shift is released, go back to the normal LED values. + var cueChan1LedValue = + engine.getValue('[Channel1]', 'pfl') ? 0x7F : 0x00; + midi.sendShortMsg(0x91, 0x0C, cueChan1LedValue); + var cueChan2LedValue = + engine.getValue('[Channel2]', 'pfl') ? 0x7F : 0x00; + midi.sendShortMsg(0x92, 0x0C, cueChan2LedValue); + } +}; + + +DJCStarlight.shutdown = function() { + // Reset base LED + midi.sendShortMsg(0x90,0x24,0x7F); +};