summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-04-17 16:59:00 +0200
committerJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-04-17 16:59:00 +0200
commita4b989e4696b2c1cba37653a9c18bcf6973d14a2 (patch)
treea747ce296af00f7e1dc642234cebda19e9155762
parentd7982123f50df2568b99fc29173bc4add242fb79 (diff)
parent8562750da708b1ef772d2ff71d644232a5e940a4 (diff)
Merge branch '2.3' of github.com:mixxxdj/mixxx
-rw-r--r--.github/workflows/build.yml47
-rw-r--r--res/controllers/Denon-MC7000-scripts.js334
-rw-r--r--tools/deploy.py327
-rwxr-xr-xtools/deploy.sh54
-rw-r--r--tools/generate_download_metadata.py211
5 files changed, 573 insertions, 400 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 74cf792483..02817fe8dd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -95,8 +95,8 @@ jobs:
runs-on: ${{ matrix.os }}
name: ${{ matrix.name }}
outputs:
- artifact-macos-macosintel: ${{ steps.generate_artifact_metadata.outputs.artifact-macos-macosintel }}
- artifact-windows-windows64: ${{ steps.generate_artifact_metadata.outputs.artifact-windows-windows64 }}
+ artifact-macos-macosintel: ${{ steps.prepare_deploy.outputs.artifact-macos-macosintel }}
+ artifact-windows-windows64: ${{ steps.prepare_deploy.outputs.artifact-windows-windows64 }}
steps:
# sccache's handling of the /fp:fast MSVC compiler option is broken, so use our fork with the fix.
@@ -306,6 +306,21 @@ jobs:
run: signtool sign /f $Env:WINDOWS_CODESIGN_CERTIFICATE_PATH /p $Env:WINDOWS_CODESIGN_CERTIFICATE_PASSWORD *.msi
working-directory: build
+ - name: "Prepare for deployment"
+ # Copy the desired directory structure to the deploy/ directory. This
+ # also generates metadata for file artifact and write it to the job
+ # output using the artifacts_slug value.
+ id: prepare_deploy
+ if: github.event_name == 'push'
+ shell: bash
+ run: >
+ python3 tools/deploy.py prepare-deployment
+ --slug '${{ matrix.artifacts_slug }}'
+ --output-dir 'deploy/'
+ --dest-path 'builds/{branch}/${{ runner.os }}/{filename}'
+ --dest-url 'https://downloads.mixxx.org'
+ ${{ matrix.artifacts_path }}
+
- name: "[Windows] Install rsync and openssh"
env:
SSH_PASSWORD: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD }}
@@ -315,30 +330,16 @@ jobs:
pacman -S --noconfirm coreutils bash rsync openssh
Add-Content -Path "$Env:GITHUB_ENV" -Value "PATH=$Env:PATH"
- - name: "Generate Artifact Metadata"
- # Generate metadata for file artifact and write it to the job output
- # using the artifacts_slug value. This also sets the DEPLOY_DIR
- # environment variable that is used in the deploy.sh script in the next
- # step.
- id: generate_artifact_metadata
- if: github.event_name == 'push'
- run: python3 tools/generate_download_metadata.py artifact ${{ matrix.artifacts_path }} "${{ matrix.artifacts_slug }}"
- env:
- DEPLOY_BASEURL: "https://downloads.mixxx.org"
- DESTDIR: builds/{git_branch}/${{ runner.os }}
-
- name: "[macOS/Windows] Upload build to downloads.mixxx.org"
# skip deploying Ubuntu builds to downloads.mixxx.org because these are deployed to the PPA
if: runner.os != 'Linux' && github.event_name == 'push' && env.SSH_PASSWORD != null
- run: bash tools/deploy.sh ${{ matrix.artifacts_path }}
+ run: bash tools/deploy.sh deploy/
env:
DESTDIR: public_html/downloads/
- DEPLOY_ONLY: 0
SSH_HOST: downloads-hostgator.mixxx.org
SSH_KEY: packaging/certificates/downloads-hostgator.mixxx.org.key
SSH_PASSWORD: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD }}
SSH_USER: mixxx
- UPLOAD_ID: ${{ github.run_id }}
# Workaround for https://github.com/actions/cache/issues/531
- name: Use system tar & zstd from Chocolatey for caching
@@ -367,24 +368,24 @@ jobs:
# Retrieve the metadata from the matrix job's outputs, merge them into a
# single JSON document and then deploy to the server.
if: github.event_name == 'push' && env.SSH_PASSWORD != null
- run: python3 tools/generate_download_metadata.py manifest
+ run: >
+ python3 tools/deploy.py generate-manifest
+ --output-dir 'deploy/'
+ --dest-path 'builds/{branch}/manifest.json'
+ --dest-url 'https://downloads.mixxx.org'
env:
JOB_DATA: ${{ toJSON(needs.build) }}
- MANIFEST_URL: "https://downloads.mixxx.org/builds/{git_branch}/manifest.json"
- DESTDIR: "builds/{git_branch}"
SSH_PASSWORD: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD }}
- name: "Deploy Manifest"
if: github.event_name == 'push' && env.SSH_PASSWORD != null && env.MANIFEST_DIRTY != null && env.MANIFEST_DIRTY != '0'
- run: bash tools/deploy.sh manifest.json
+ run: bash tools/deploy.sh deploy/
env:
DESTDIR: public_html/downloads/
- DEPLOY_ONLY: 1
SSH_HOST: downloads-hostgator.mixxx.org
SSH_KEY: packaging/certificates/downloads-hostgator.mixxx.org.key
SSH_PASSWORD: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD }}
SSH_USER: mixxx
- UPLOAD_ID: ${{ github.run_id }}
- name: "Trigger Netlify build"
if: env.NETLIFY_BUILD_HOOK != null && env.MANIFEST_DIRTY != null && env.MANIFEST_DIRTY != '0'
diff --git a/res/controllers/Denon-MC7000-scripts.js b/res/controllers/Denon-MC7000-scripts.js
index fea38f8b2e..9381cb9365 100644
--- a/res/controllers/Denon-MC7000-scripts.js
+++ b/res/controllers/Denon-MC7000-scripts.js
@@ -32,6 +32,13 @@ var MC7000 = {};
// USER VARIABLES BEGIN //
///////////////////////////////////*/
+// switch on experimental features
+// experimental features are:
+// 1) Beat LED in Slicer mode (counts every 8 beats AFTER the CUE point)
+// only works for CONSTANT TEMPO tracks
+// needs beat grid and CUE point set
+MC7000.experimental = false;
+
// Wanna have Needle Search active while playing a track ?
// In any case Needle Search is available holding "SHIFT" down.
// can be true or false (recommended: false)
@@ -61,18 +68,18 @@ MC7000.VinylModeOn = true; // default: true
// Scratch algorithm parameters
MC7000.scratchParams = {
- recordSpeed: 33.3, // default: 33.3
+ recordSpeed: 33 + 1/3, // default: 33 + 1/3
alpha: (1.0/10), // default: (1.0/10)
beta: (1.0/10)/32 // default: (1.0/10)/32
};
-// Sensitivity of the jog wheel (also depends on audio latency)
-MC7000.jogParams = {
- // Sensitivity factor (0.5 for half, 2 for double sensitivity)
- jogSensitivity: 1, // default: 1
- // this will limit the parameter of "jog" (keep between 0.5 and 3)
- maxJogValue: 3 // default: 3
-};
+// Sensitivity factor of the jog wheel (also depends on audio latency)
+// 0.5 for half, 2 for double sensitivity - Recommendation:
+// set to 0.5 with audio buffer set to 50ms
+// set to 1 with audio buffer set to 25ms
+// set to 3 with audio buffer set to 5ms
+
+MC7000.jogSensitivity = 1; // default: 1.0 with audio buffer set to 23ms
/*/////////////////////////////////
// USER VARIABLES END //
@@ -99,7 +106,7 @@ MC7000.currentRateRangeIndex = [0, 0, 0, 0];
// initialize the "factor" function for Spinback
MC7000.factor = [];
-//Set Shift button state to false for default
+//Set Shift button state to false as default
MC7000.shift = [false, false, false, false];
// initialize the PAD Mode to Hot Cue and all others off when starting
@@ -114,32 +121,46 @@ MC7000.PADModeSampler = [false, false, false, false];
MC7000.PADModeVelSamp = [false, false, false, false];
MC7000.PADModePitch = [false, false, false, false];
-// Beatloop Roll sizes
+// PAD Mode 'Beatloop Roll' sizes
MC7000.beatLoopRoll = [1 / 16, 1 / 8, 1 / 4, 1 / 2, 1, 2, 4, 8];
+// PAD Mode - 'Fixed Loop' sizes
+MC7000.fixedLoop = [1, 2, 4, 8, 16, 32, 64, 128];
+
+// PAD Mode - 'Beatjump' sizes
+MC7000.beatJump = [1, 2, 4, 8, 16, 32, 64, 128];
+
// Define the MIDI signal for red LED at VU Meters
MC7000.VuMeterLEDPeakValue = 0x76;
+// initialize variables to compare LED status for VU, Jog and PAD LEDs
+MC7000.prevVuLevel = [0, 0, 0, 0];
+MC7000.prevJogLED = [0, 0, 0, 0];
+MC7000.prevPadLED = [0, 0, 0, 0];
+
// PAD Mode Colors
MC7000.padColor = {
"alloff": 0x01, // switch off completely
// Hot Cue
- "hotcueon": 0x04, // darkblue Hot Cue active
- "hotcueoff": 0x02, // lightblue Hot Cue inactive
+ "hotcueon": 0x04, // blue Hot Cue active
+ "hotcueoff": 0x02, // dark blue Hot Cue inactive
// Cue Loop
- "cueloopon": 0x0D, // Cueloop colour for activated cue point
- "cueloopoff": 0x1A, // Cueloop colour inactive
+ "cueloopon": 0x0D, // green Cueloop colour for activated cue point
+ "cueloopoff": 0x1A, // dark green Cueloop colour inactive
// Roll
- "rollon": 0x20, // BeatloopRoll active colour
- "rolloff": 0x06, // BeatloopRoll off colour
+ "rollon": 0x20, // cyan BeatloopRoll active colour
+ "rolloff": 0x06, // dark cyan BeatloopRoll off colour
+ // Saved Loop
+ "fixedloopon": 0x3D, // yellow Saved Loop active
+ "fixedloopoff": 0x15, // dark yellow Saved Loop active
// Slicer
- "sliceron": 0x11, // activated Slicer
- "slicerJumpFwd": 0x31, // Sliver forward jump
- "slicerJumpBack": 0x31, // Sliver backward jump
+ "sliceron": 0x11, // dark red activated Slicer
+ "slicerJumpFwd": 0x31, // red Sliver forward jump
+ "slicerJumpBack": 0x31, // red Sliver backward jump
// Sampler
- "samplerloaded": 0x38, // dark pink Sampler loaded colour
+ "samplerloaded": 0x38, // pink Sampler loaded colour
"samplerplay": 0x09, // green Sampler playing
- "sampleroff": 0x12 // light pink Sampler standard colour
+ "sampleroff": 0x12 // dark pink Sampler standard colour
};
/* DECK INITIALIZATION */
@@ -158,15 +179,17 @@ MC7000.init = function() {
engine.makeConnection("[Channel3]", "VuMeter", MC7000.VuMeter);
engine.makeConnection("[Channel4]", "VuMeter", MC7000.VuMeter);
- // Platter Ring LED
+ // Platter Ring LED mode
midi.sendShortMsg(0x90, 0x64, MC7000.modeSingleLED);
midi.sendShortMsg(0x91, 0x64, MC7000.modeSingleLED);
midi.sendShortMsg(0x92, 0x64, MC7000.modeSingleLED);
midi.sendShortMsg(0x93, 0x64, MC7000.modeSingleLED);
- engine.makeConnection("[Channel1]", "playposition", MC7000.JogLed);
- engine.makeConnection("[Channel2]", "playposition", MC7000.JogLed);
- engine.makeConnection("[Channel3]", "playposition", MC7000.JogLed);
- engine.makeConnection("[Channel4]", "playposition", MC7000.JogLed);
+
+ // Track Position LEDs for Jog Wheel and Slicer
+ engine.makeConnection("[Channel1]", "playposition", MC7000.TrackPositionLEDs);
+ engine.makeConnection("[Channel2]", "playposition", MC7000.TrackPositionLEDs);
+ engine.makeConnection("[Channel3]", "playposition", MC7000.TrackPositionLEDs);
+ engine.makeConnection("[Channel4]", "playposition", MC7000.TrackPositionLEDs);
// Vinyl mode LEDs
midi.sendShortMsg(0x90, 0x07, MC7000.isVinylMode ? 0x7F: 0x01);
@@ -188,8 +211,8 @@ MC7000.init = function() {
engine.makeConnection("[Sampler"+i+"]", "play", MC7000.SamplerLED);
}
- // Activate Timer for Controller Status SysEx to avoid conflicts with Softtakeover
- engine.beginTimer(3000, MC7000.delayedSysEx, true);
+ // send Controller Status SysEx message delayed to avoid conflicts with Softtakeover
+ engine.beginTimer(2000, MC7000.delayedSysEx, true);
};
// SysEx message to receive all knob and fader positions
@@ -215,6 +238,7 @@ MC7000.samplerLevel = function(channel, control, value) {
// PAD Mode Hot Cue
MC7000.padModeCue = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -232,9 +256,9 @@ MC7000.padModeCue = function(channel, control, value, status, group) {
// change PAD color when switching to Hot Cue Mode
for (var i = 1; i <= 8; i++) {
if (engine.getValue(group, "hotcue_" + i + "_enabled", true)) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.hotcueon);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i - 1, MC7000.padColor.hotcueon);
} else {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.hotcueoff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i - 1, MC7000.padColor.hotcueoff);
}
}
};
@@ -242,6 +266,7 @@ MC7000.padModeCue = function(channel, control, value, status, group) {
// PAD Mode Cue Loop
MC7000.padModeCueLoop = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -257,14 +282,15 @@ MC7000.padModeCueLoop = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.alloff);
}
};
// PAD Mode Flip
MC7000.padModeFlip = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -280,14 +306,15 @@ MC7000.padModeFlip = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.alloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x1C + i, MC7000.padColor.alloff);
}
};
// PAD Mode Roll
MC7000.padModeRoll = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -303,14 +330,15 @@ MC7000.padModeRoll = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// change PAD color when switching to Roll Mode
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.rolloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.rolloff);
}
};
// PAD Mode Saved Loop
MC7000.padModeSavedLoop = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -325,15 +353,17 @@ MC7000.padModeSavedLoop = function(channel, control, value, status, group) {
MC7000.PADModeVelSamp[deckNumber] = false;
MC7000.PADModePitch[deckNumber] = false;
- // switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff);
+ // change PAD color when switching to Saved Loop Mode
+ for (var i = 0; i < 8; i++) {
+ var activeLED = engine.getValue(group, "beatloop_" + MC7000.fixedLoop[i] + "_enabled") ? MC7000.padColor.fixedloopon : MC7000.padColor.fixedloopoff;
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, activeLED);
}
};
// PAD Mode Slicer
MC7000.padModeSlicer = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -349,14 +379,15 @@ MC7000.padModeSlicer = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// change PAD color when switching to Slicer Mode
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.sliceron);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.sliceron);
}
};
// PAD Mode Slicer Loop
MC7000.padModeSlicerLoop = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -372,14 +403,15 @@ MC7000.padModeSlicerLoop = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.alloff);
}
};
// PAD Mode Sampler
MC7000.padModeSampler = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -397,11 +429,11 @@ MC7000.padModeSampler = function(channel, control, value, status, group) {
// change PAD color when switching to Sampler Mode
for (var i = 1; i <= 8; i++) {
if (engine.getValue("[Sampler" + i + "]", "play")) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.samplerplay);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i - 1, MC7000.padColor.samplerplay);
} else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 0) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.sampleroff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i - 1, MC7000.padColor.sampleroff);
} else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 1 && engine.getValue("[Sampler" + i + "]", "play") === 0) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.samplerloaded);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i - 1, MC7000.padColor.samplerloaded);
}
}
};
@@ -409,6 +441,7 @@ MC7000.padModeSampler = function(channel, control, value, status, group) {
// PAD Mode Velocity Sampler
MC7000.padModeVelSamp = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -424,14 +457,15 @@ MC7000.padModeVelSamp = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = false;
// switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.alloff);
}
};
// PAD Mode Pitch
MC7000.padModePitch = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (value === 0x00) {
return; // don't respond to note off messages
}
@@ -447,19 +481,21 @@ MC7000.padModePitch = function(channel, control, value, status, group) {
MC7000.PADModePitch[deckNumber] = true;
// switch off PAD illumination
- for (var i = 1; i <= 8; i++) {
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.alloff);
+ for (var i = 0; i < 8; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.alloff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x1C + i, MC7000.padColor.alloff);
}
};
// PAD buttons
MC7000.PadButtons = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
+ var i, j;
// activate and clear Hot Cues
if (MC7000.PADModeCue[deckNumber] && engine.getValue(group, "track_loaded") === 1) {
- for (var i = 1; i <= 8; i++) {
+ for (i = 1; i <= 8; i++) {
if (control === 0x14 + i - 1 && value >= 0x01) {
engine.setValue(group, "hotcue_" + i + "_activate", true);
} else {
@@ -467,7 +503,7 @@ MC7000.PadButtons = function(channel, control, value, status, group) {
}
if (control === 0x1C + i - 1 && value >= 0x01) {
engine.setValue(group, "hotcue_" + i + "_clear", true);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.hotcueoff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x1C + i - 1, MC7000.padColor.hotcueoff);
}
}
} else if (MC7000.PADModeCueLoop[deckNumber]) {
@@ -475,30 +511,48 @@ MC7000.PadButtons = function(channel, control, value, status, group) {
} else if (MC7000.PADModeFlip[deckNumber]) {
return;
} else if (MC7000.PADModeRoll[deckNumber]) {
- // todo:
- // check for actual beatloop_size and apply back after a PAD Roll
+ // TODO(all): check for actual beatloop_size and apply back after a PAD Roll
i = control - 0x14;
if (control === 0x14 + i && value > 0x00) {
engine.setValue(group, "beatlooproll_" + MC7000.beatLoopRoll[i] + "_activate", true);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, MC7000.padColor.rollon);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.rollon);
} else if (control === 0x14 + i && value === 0x00) {
engine.setValue(group, "beatlooproll_activate", false);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, MC7000.padColor.rolloff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.rolloff);
}
} else if (MC7000.PADModeSavedLoop[deckNumber]) {
- return;
+ if (value === 0x00) {
+ return; // don't respond to note off messages
+ }
+ i = control - 0x14;
+ engine.setValue(group, "beatloop_" + MC7000.fixedLoop[i] + "_toggle", true);
+ for (j =0; j < 8; j++) {
+ var activeLED = engine.getValue(group, "beatloop_" + MC7000.fixedLoop[j] + "_enabled") ? MC7000.padColor.fixedloopon : MC7000.padColor.fixedloopoff;
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + j, activeLED);
+ }
} else if (MC7000.PADModeSlicer[deckNumber]) {
if (value > 0) {
- var beats = 1 << (control % 4);
- if (control > 0x17) {
- engine.setValue(group, "beatjump_" + beats + "_backward", value);
- midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.slicerJumpBack);
- } else {
- engine.setValue(group, "beatjump_" + beats + "_forward", value);
- midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.slicerJumpFwd);
+ i = control - 0x14; // unshifted button
+ j = control - 0x1C; // shifted button
+ // forward buttons (PAD buttons upper row)
+ if (control >= 0x14 && control <= 0x17) {
+ engine.setValue(group, "beatjump_" + MC7000.beatJump[i] + "_forward", true);
+ midi.sendShortMsg(0x94 + deckOffset, control, MC7000.padColor.slicerJumpFwd);
+ // backward buttons (PAD buttons lower row)
+ } else if (control >= 0x18 && control <= 0x1B) {
+ engine.setValue(group, "beatjump_" + MC7000.beatJump[i - 4] + "_backward", true);
+ midi.sendShortMsg(0x94 + deckOffset, control, MC7000.padColor.slicerJumpBack);
+ // forward buttons (PAD buttons upper row - shifted controls)
+ } else if (control >= 0x1C && control <= 0x1F) {
+ engine.setValue(group, "beatjump_" + MC7000.beatJump[j + 4] + "_forward", true);
+ midi.sendShortMsg(0x94 + deckOffset, control, MC7000.padColor.slicerJumpFwd);
+ // backward buttons (PAD buttons lower row - shifted controls)
+ } else if (control >= 0x20 && control <= 0x23) {
+ engine.setValue(group, "beatjump_" + MC7000.beatJump[j] + "_backward", true);
+ midi.sendShortMsg(0x94 + deckOffset, control, MC7000.padColor.slicerJumpBack);
}
} else {
- midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.sliceron);
+ midi.sendShortMsg(0x94 + deckOffset, control, MC7000.padColor.sliceron);
}
} else if (MC7000.PADModeSlicerLoop[deckNumber]) {
return;
@@ -513,10 +567,10 @@ MC7000.PadButtons = function(channel, control, value, status, group) {
} else if (control === 0x1C + i - 1 && value >= 0x01) {
if (engine.getValue("[Sampler" + i + "]", "play") === 1) {
engine.setValue("[Sampler" + i + "]", "cue_gotoandstop", 1);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.samplerloaded);
+ midi.sendShortMsg(0x94 + deckOffset, 0x1C + i - 1, MC7000.padColor.samplerloaded);
} else {
engine.setValue("[Sampler" + i + "]", "eject", 1);
- midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.sampleroff);
+ midi.sendShortMsg(0x94 + deckOffset, 0x1C + i - 1, MC7000.padColor.sampleroff);
engine.setValue("[Sampler" + i + "]", "eject", 0);
}
}
@@ -528,12 +582,12 @@ MC7000.PadButtons = function(channel, control, value, status, group) {
}
};
-// Toggle Shift Button
+// Shift Button
MC7000.shiftButton = function(channel, control, value, status, group) {
- var deckNumber = script.deckFromGroup(group);
- MC7000.shift[deckNumber - 1] = ! MC7000.shift[deckNumber - 1];
- midi.sendShortMsg(0x90 + deckNumber - 1, 0x32,
- MC7000.shift[deckNumber - 1] ? 0x7F : 0x01);
+ var deckOffset = script.deckFromGroup(group) - 1;
+ MC7000.shift[deckOffset] = ! MC7000.shift[deckOffset];
+ midi.sendShortMsg(0x90 + deckOffset, 0x32,
+ MC7000.shift[deckOffset] ? 0x7F : 0x01);
};
// Toggle Vinyl Mode
@@ -541,10 +595,10 @@ MC7000.vinylModeToggle = function(channel, control, value, status, group) {
if (value === 0x00) {
return; // don't respond to note off messages
}
- var deckNumber = script.deckFromGroup(group);
- MC7000.isVinylMode[deckNumber - 1] = !MC7000.isVinylMode[deckNumber - 1];
- midi.sendShortMsg(0x90 + deckNumber - 1, 0x07,
- MC7000.isVinylMode[deckNumber - 1] ? 0x7F : 0x01);
+ var deckOffset = script.deckFromGroup(group) - 1;
+ MC7000.isVinylMode[deckOffset] = !MC7000.isVinylMode[deckOffset];
+ midi.sendShortMsg(0x90 + deckOffset, 0x07,
+ MC7000.isVinylMode[deckOffset] ? 0x7F : 0x01);
};
// Use select button to load and eject track from deck
@@ -585,7 +639,8 @@ MC7000.loadButton = function(channel, control, value, status, group) {
// The button that enables/disables scratching
MC7000.wheelTouch = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
- if (MC7000.isVinylMode[deckNumber - 1]) {
+ var deckOffset = deckNumber - 1;
+ if (MC7000.isVinylMode[deckOffset]) {
if (value === 0x7F) {
engine.scratchEnable(deckNumber, MC7000.jogWheelTicksPerRevolution,
MC7000.scratchParams.recordSpeed,
@@ -599,22 +654,27 @@ MC7000.wheelTouch = function(channel, control, value, status, group) {
// The wheel that actually controls the scratching
MC7000.wheelTurn = function(channel, control, value, status, group) {
+ // TODO(all): check for latency and use it to normalize the jog factor so jog wont be
+ // depending on audio latency anymore.
+
// A: For a control that centers on 0:
var numTicks = (value < 0x64) ? value : (value - 128);
+ var adjustedSpeed = numTicks * MC7000.jogSensitivity * 25;
var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
if (engine.isScratching(deckNumber)) {
// Scratch!
- engine.scratchTick(deckNumber, numTicks);
+ engine.scratchTick(deckNumber, numTicks * MC7000.jogSensitivity);
} else {
- if (MC7000.shift[deckNumber - 1]) {
+ if (MC7000.shift[deckOffset]) {
// While Shift Button pressed -> Search through track
- var jogSearch = 5000 * numTicks / MC7000.jogWheelTicksPerRevolution * MC7000.jogParams.jogSensitivity;
+ var jogSearch = 300 * adjustedSpeed / MC7000.jogWheelTicksPerRevolution;
engine.setValue(group, "jog", jogSearch);
} else {
// While Shift Button released -> Pitch Bend
- var jogDelta = numTicks / MC7000.jogWheelTicksPerRevolution * MC7000.jogParams.jogSensitivity * 30;
+ var jogDelta = adjustedSpeed / MC7000.jogWheelTicksPerRevolution;
var jogAbsolute = jogDelta + engine.getValue(group, "jog");
- engine.setValue(group, "jog", Math.max(-MC7000.jogParams.maxJogValue, Math.min(MC7000.jogParams.maxJogValue, jogAbsolute)));
+ engine.setValue(group, "jog", jogAbsolute);
}
}
};
@@ -646,7 +706,7 @@ MC7000.needleSearchStripPosition = function(channel, control, value, status,
group) {
var deckNumber = script.deckFromGroup(group);
if (MC7000.needleSearchTouched[deckNumber]) {
- var fullValue = (MC7000.needleDropMSB << 7) + value; // move MSB 7 binary gigits to the left and add LSB
+ var fullValue = (MC7000.needleDropMSB << 7) + value; // move MSB 7 binary digits to the left and add LSB
var position = (fullValue / 0x3FFF); // divide by all possible positions to get relative between 0 - 1
engine.setParameter(group, "playposition", position);
}
@@ -669,13 +729,13 @@ MC7000.nextRateRange = function(midichan, control, value, status, group) {
if (value === 0) {
return; // don't respond to note off messages
}
- var deckNumber = script.deckFromGroup(group);
+ var deckOffset = script.deckFromGroup(group) - 1;
// increment currentRateRangeIndex and check for overflow
- if (++MC7000.currentRateRangeIndex[deckNumber - 1] ===
+ if (++MC7000.currentRateRangeIndex[deckOffset] ===
MC7000.rateRanges.length) {
- MC7000.currentRateRangeIndex[deckNumber - 1] = 0;
+ MC7000.currentRateRangeIndex[deckOffset] = 0;
}
- engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]);
+ engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckOffset]]);
};
// Previous Rate range toggle
@@ -683,19 +743,19 @@ MC7000.prevRateRange = function(midichan, control, value, status, group) {
if (value === 0) {
return; // don't respond to note off messages
}
- var deckNumber = script.deckFromGroup(group);
+ var deckOffset = script.deckFromGroup(group) - 1;
// decrement currentRateRangeIndex and check for underflow
- if (--MC7000.currentRateRangeIndex[deckNumber - 1] < 0) {
- MC7000.currentRateRangeIndex[deckNumber - 1] = MC7000.rateRanges.length - 1;
+ if (--MC7000.currentRateRangeIndex[deckOffset] < 0) {
+ MC7000.currentRateRangeIndex[deckOffset] = MC7000.rateRanges.length - 1;
}
- engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]);
+ engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckOffset]]);
};
// Key & Waveform zoom Select
MC7000.keySelect = function(midichan, control, value, status, group) {
- var deckNumber = script.deckFromGroup(group);
+ var deckOffset = script.deckFromGroup(group) - 1;
// While Shift Button is pressed: Waveform Zoom
- if (MC7000.shift[deckNumber - 1]) {
+ if (MC7000.shift[deckOffset]) {
if (value === 0x7F) {
script.triggerControl(group, "waveform_zoom_up", 100);
} else {
@@ -713,12 +773,12 @@ MC7000.keySelect = function(midichan, control, value, status, group) {
// Key & Waveform zoom Reset
MC7000.keyReset = function(channel, control, value, status, group) {
- var deckNumber = script.deckFromGroup(group);
+ var deckOffset = script.deckFromGroup(group) - 1;
if (value === 0x00) {
return;
}
// While Shift Button is pressed: Waveform Zoom Reset
- if (MC7000.shift[deckNumber - 1]) {
+ if (MC7000.shift[deckOffset]) {
script.triggerControl(group, "waveform_zoom_set_default", 100);
// While Shift Button is released: Key Reset
} else {
@@ -746,12 +806,12 @@ MC7000.stopTime = function(channel, control, value, status, group) {
MC7000.factor[deckNumber] = (1.1 - (value / 127)) * 30 - 2;
};
-// Use the CENSOR button as Spinback with STOP TIME adjusted length
+// Use SHIFT + CENSOR button as Spinback with STOP TIME adjusted length
MC7000.reverse = function(channel, control, value, status, group) {
var deckNumber = script.deckFromGroup(group);
if (value > 0) {
// while the button is pressed spin back
- engine.brake(deckNumber, true, MC7000.factor[deckNumber], -15); // start at a rate of -15 and decrease by "factor"
+ engine.brake(deckNumber, true, MC7000.factor[deckNumber], - 15); // start at a rate of -15 and decrease by "factor"
} else {
// when releasing the button the track starts softly again
engine.softStart(deckNumber, true, MC7000.factor[deckNumber]);
@@ -784,7 +844,7 @@ MC7000.crossFaderCurve = function(control, value) {
// Set FX wet/dry value
MC7000.fxWetDry = function(channel, control, value, status, group) {
- var numTicks = (value < 0x64) ? value: (value - 128);
+ var numTicks = (value < 0x64) ? value : (value - 128);
var newVal = engine.getValue(group, "mix") + numTicks/64*2;
engine.setValue(group, "mix", Math.max(0, Math.min(1, newVal)));
};
@@ -815,40 +875,86 @@ MC7000.sortLibrary = function(channel, control, value) {
/* LEDs for VuMeter */
// VuMeters only for Channel 1-4 / Master is on Hardware
MC7000.VuMeter = function(value, group) {
- var deckNumber = script.deckFromGroup(group),
- vuLevelOutValue = engine.getValue(group, "PeakIndicator") ? MC7000.VuMeterLEDPeakValue : Math.pow(value, 4) * (MC7000.VuMeterLEDPeakValue - 1);
-
- midi.sendShortMsg(0xB0 + deckNumber - 1, 0x1F, vuLevelOutValue);
+ var deckOffset = script.deckFromGroup(group) - 1;
+ // sends either PeakIndicator or scales value (0..1) to (0..117) while truncating to each LED
+ var vuLevelOutValue = engine.getValue(group, "PeakIndicator") ? MC7000.VuMeterLEDPeakValue : Math.floor(Math.pow(value, 2.5) * 9) * 13;
+ // only send Midi signal when LED value has changed
+ if (MC7000.prevVuLevel[deckOffset] !== vuLevelOutValue) {
+ midi.sendShortMsg(0xB0 + deckOffset, 0x1F, vuLevelOutValue);
+ MC7000.prevVuLevel[deckOffset] = vuLevelOutValue;
+ }
};
-/* LEDs around Jog wheel */
-MC7000.JogLed = function(value, group) {
+// Spinning Platter LEDs & Slicer Loop PAD LEDs as beat counter
+// pulled together for the calculation to be done only once and then
+// send LED signals to Jog or PAD LEDs when needed.
+MC7000.TrackPositionLEDs = function(value, group) {
// do nothing before track starts
if (value === 0) {
return;
}
- var deckNumber = script.deckFromGroup(group),
- trackDuration = engine.getValue(group, "duration"),
- position = value * trackDuration / 60 * MC7000.scratchParams.recordSpeed,
- // LED ring contains 48 segments with each LED activated by the next even number
- jogLedOutValue = 48 * 2,
- activeLED = MC7000.isVinylMode[deckNumber - 1] ? Math.round(position * jogLedOutValue) % jogLedOutValue : value * jogLedOutValue;
+ // lets define some variables first
+ var deckNumber = script.deckFromGroup(group);
+ var deckOffset = deckNumber - 1;
+ var trackDuration = engine.getValue(group, "duration"); // in seconds
+ var beatLength = engine.getValue(group, "file_bpm") / 60; // in Beats Per Seconds
+ var cuePosition = engine.getValue(group, "cue_point") / engine.getValue(group, "track_samplerate") / 2; // in seconds
+ var playPosition = value * trackDuration; // in seconds
+ var jogLEDPosition = playPosition / 60 * MC7000.scratchParams.recordSpeed;
+ var jogLEDNumber = 48; // LED ring contains 48 segments each triggered by the next even Midi value
+ // check for Vinyl Mode and decide to spin the Jog LED or show play position
+ var activeJogLED = MC7000.isVinylMode[deckOffset] ? Math.round(jogLEDPosition * jogLEDNumber) % jogLEDNumber : Math.round(value * jogLEDNumber);
+ // count the beats (1 to 8) after the CUE point
+ var beatCountLED = (Math.floor((playPosition - cuePosition) * beatLength) % 8); //calculate PAD LED position
+
+ // TODO(all): check for playposition < (trackduration - warning length) for sending position signals
+ // check if a Jog LED has changed and if so then send the signal to the next Jog LED
+ if (MC7000.prevJogLED[deckOffset] !== activeJogLED) {
+ midi.sendShortMsg(0x90 + deckOffset, 0x06, activeJogLED * 2); // only each 2nd midi signal triggers the next LED
+ MC7000.prevJogLED[deckOffset] = activeJogLED;
+ }
+ // TODO(all): else blink the platter LEDs
- midi.sendShortMsg(0x90 + deckNumber - 1, 0x06, activeLED);
+ // check if Slicer mode is active and illuminate PAD LEDs counting with the beat while playing
+ if (!MC7000.experimental) {
+ return;
+ }
+ if (MC7000.PADModeSlicer[deckNumber]) {
+ // only send new LED status when beatCountLED really changes
+ if (MC7000.prevPadLED[deckOffset] !== beatCountLED) {
+ // first set all LEDs to default color incl shifted
+ for (var i = 0; i < 16; i++) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + i, MC7000.padColor.sliceron);
+ }
+ // now chose which PAD LED to turn on (+8 means shifted PAD LEDs)
+ if (beatCountLED === 0) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x14, MC7000.padColor.hotcueon);
+ midi.sendShortMsg(0x94 + deckOffset, 0x14 + 8, MC7000.padColor.hotcueon);
+ } else if (beatCountLED === 7) {
+ midi.sendShortMsg(0x94 + deckOffset, 0x1B, MC7000.padColor.hotcueon);
+ midi.sendShortMsg(0