I have updated the midi configuration for Hercules RMX to work better
with Mixxx 1.8.0. A patch is attached. See changes below.
I have a few questions also:
1. Has timers been implemented yet?
2. The list of controls for midi mapping on the wiki seem to be
incomplete. Is the there a complete list?
3. Jog wheel seeking is considerably slower in 1.8.0beta1 than 1.7.1.
Has something changed? On my RMX set to "normal" 1s equals to ~15
revolutions.
4. Scratch doesn't seem to work well on a stopped track. Track moves
much faster backwards that forward. Why?
5. Can scratch decay be handled by the engine instead of scripts?
Don't all controls need a common handling of that?
Changes:
*Forward and backward buttons used for seeking (fwd/back) instead of
skipping to next/previous track.
*Beat sync is handled through a script to turn on button LEds.
*Pitch Reset implemented through script.
*Reset of Sync and Reset LEDs through script bound to rate.
*Previous and next split into separate script functions to enable remapping.
*Left and Right connected to playlist naviation
Select[Next/Prev]Playlist. (Seem to be track selection though)
*Looping connected, buttons 2, 5 and 6 mapped to loop_in, loop_out and
reloop_exit
*Speedup of jog wheel seeking in a stopped track.
*Removed getGroup in favour of group parameter.
*Fixed jog wheel scroll in library.
*Fixed cue play behaviour. Now playing as long as Cue is held down.
//Anders
=== modified file 'mixxx/res/midi/Hercules DJ Console RMX.midi.xml'
--- mixxx/res/midi/Hercules DJ Console RMX.midi.xml 2009-05-25 23:04:13 +0000
+++ mixxx/res/midi/Hercules DJ Console RMX.midi.xml 2010-02-28 23:46:08 +0000
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
-<MixxxMIDIPreset vschemaVersion="1" mixxxVersion="1.7.0">
+<MixxxMIDIPreset vschemaVersion="1" mixxxVersion="1.8.0">
<info>
<name>Hercules DJ Console RMX</name>
<author>Garth Dahlstrom</author>
+ <author>Anders Gunnarsson</author>
<description>This is a complete mapping for a Hercules DJ Console RMX. Requires scripting.</description>
</info>
<controller id="Hercules DJ Console RMX MIDI">
@@ -161,7 +162,7 @@
</control>
<control>
<group>[Channel1]</group>
- <key>PrevTrack</key>
+ <key>back</key>
<status>0xB0</status>
<midino>0x09</midino>
<options>
@@ -170,7 +171,7 @@
</control>
<control>
<group>[Channel1]</group>
- <key>NextTrack</key>
+ <key>fwd</key>
<status>0xB0</status>
<midino>0x0A</midino>
<options>
@@ -191,7 +192,6 @@
<midino>0x31</midino>
<options/>
</control>
-
<control>
<group>[Master]</group>
<key>volume</key>
@@ -258,7 +258,7 @@
</control>
<control>
<group>[Channel2]</group>
- <key>PrevTrack</key>
+ <key>back</key>
<status>0xB0</status>
<midino>0x21</midino>
<options>
@@ -267,7 +267,7 @@
</control>
<control>
<group>[Channel2]</group>
- <key>NextTrack</key>
+ <key>fwd</key>
<status>0xB0</status>
<midino>0x22</midino>
<options>
@@ -363,20 +363,38 @@
<!-- Sync Buttons -->
<control>
<group>[Channel1]</group>
- <key>beatsync</key>
+ <key>HerculesRMX.beatSync</key>
<status>0xB0</status>
<midino>0x07</midino>
<options>
- <Button/>
+ <Script-Binding/>
</options>
</control>
<control>
<group>[Channel2]</group>
- <key>beatsync</key>
+ <key>HerculesRMX.beatSync</key>
<status>0xB0</status>
<midino>0x1F</midino>
<options>
- <Button/>
+ <Script-Binding/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel1]</group>
+ <key>HerculesRMX.rateReset</key>
+ <status>0xB0</status>
+ <midino>0x11</midino>
+ <options>
+ <Script-Binding/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel2]</group>
+ <key>HerculesRMX.rateReset</key>
+ <status>0xB0</status>
+ <midino>0x20</midino>
+ <options>
+ <Script-Binding/>
</options>
</control>
<control>
@@ -389,7 +407,7 @@
</options>
</control>
<control>
- <key>HerculesRMX.up_down_arrows</key>
+ <key>HerculesRMX.prev</key>
<group>[Playlist]</group>
<status>0xB0</status>
<midino>0x2A</midino>
@@ -398,7 +416,7 @@
</options>
</control>
<control>
- <key>HerculesRMX.up_down_arrows</key>
+ <key>HerculesRMX.next</key>
<group>[Playlist]</group>
<status>0xB0</status>
<midino>0x2B</midino>
@@ -407,6 +425,24 @@
</options>
</control>
<control>
+ <key>SelectPrevPlaylist</key>
+ <group>[Playlist]</group>
+ <status>0xB0</status>
+ <midino>0x2C</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <key>SelectNextPlaylist</key>
+ <group>[Playlist]</group>
+ <status>0xB0</status>
+ <midino>0x2D</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
<group>[Channel1]</group>
<key>reverse</key>
<status>0xB0</status>
@@ -424,137 +460,60 @@
<Switch/>
</options>
</control>
-
-<!--
- <control>
- <group>[Master]</group>
- <key>headMix</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>transform</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>start</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>end</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>cue_gotoandstop</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>wheel_touch_switch</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>rate_temp_up</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>rate_temp_down</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel1]</group>
- <key>loop</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>transform</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>start</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>end</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>cue_gotoandstop</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>wheel_touch_sensor</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>wheel_touch_switch</key>
- <status>0xB0</status>
- <midino>40x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>rate_temp_up</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>rate_temp_down</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options>
- <Invert/>
- </options>
- </control>
- <control>
- <group>[Channel2]</group>
- <key>loop</key>
- <status>0xB0</status>
- <midino>0x2E</midino>
- <options/>
- </control>
--->
+ <control>
+ <group>[Channel1]</group>
+ <key>loop_in</key>
+ <status>0xB0</status>
+ <midino>0x02</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel2]</group>
+ <key>loop_in</key>
+ <status>0xB0</status>
+ <midino>0x1A</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel1]</group>
+ <key>loop_out</key>
+ <status>0xB0</status>
+ <midino>0x05</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel2]</group>
+ <key>loop_out</key>
+ <status>0xB0</status>
+ <midino>0x1D</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel1]</group>
+ <key>reloop_exit</key>
+ <status>0xB0</status>
+ <midino>0x06</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
+ <control>
+ <group>[Channel2]</group>
+ <key>reloop_exit</key>
+ <status>0xB0</status>
+ <midino>0x1E</midino>
+ <options>
+ <Button/>
+ </options>
+ </control>
</controls>
<outputs>
=== modified file 'mixxx/res/midi/Hercules-DJ-Console-RMX-scripts.js'
--- mixxx/res/midi/Hercules-DJ-Console-RMX-scripts.js 2009-12-27 01:46:49 +0000
+++ mixxx/res/midi/Hercules-DJ-Console-RMX-scripts.js 2010-02-28 23:58:37 +0000
@@ -4,7 +4,11 @@
// "[Channel1] cue blink":0x3C,
// "[Channel2] cue blink":0x54,
"[Channel1] cue":0x0C,
-"[Channel2] cue":0x24
+"[Channel2] cue":0x24,
+"[Channel1] beatsync":0x07,
+"[Channel2] beatsync":0x1F,
+"[Channel1] pitchreset":0x11,
+"[Channel2] pitchreset":0x20
// "[Channel1] play":0x0B,
// "[Channel2] play":0x23
};
@@ -14,10 +18,13 @@
HerculesRMX.scratchMode = false;
HerculesRMX.playlistJogScrollMode = false;
HerculesRMX.decayLast = new Date().getTime();
-HerculesRMX.decayInterval = 50;
+HerculesRMX.decayInterval = 20;
HerculesRMX.decayRate = 300;
HerculesRMX.cueButton = { "[Channel1]": false, "[Channel2]": false};
HerculesRMX.cuePlay = { "[Channel1]": false, "[Channel2]": false};
+//HerculesRMX.scratchTimer = 0;
+HerculesRMX.scratching = false;
+HerculesRMX.syncing = false;
// TODO HerculesRMX controls should be divided into groups... then signals should directed
// to each group without thinking about specific controls to allow for easy rebinding.
@@ -32,69 +39,60 @@
engine.connectControl("[Channel1]","playposition","HerculesRMX.wheelDecay");
engine.connectControl("[Channel2]","playposition","HerculesRMX.wheelDecay");
+ engine.connectControl("[Channel1]","rate","HerculesRMX.rateChange");
+ engine.connectControl("[Channel2]","rate","HerculesRMX.rateChange");
}
HerculesRMX.wheelDecay = function (value) {
-// if (engine.getValue("[Channel1]","play") + engine.getValue("[Channel2]","play") == 0) { return; }
- engine.getValue("[Channel1]","play")
-
- var currentDate = new Date().getTime();
- // print(currentDate);
- if (currentDate > HerculesRMX.decayLast + HerculesRMX.decayInterval) {
- HerculesRMX.decayLast = currentDate;
-
- if (HerculesRMX.debug) print(" new playposition: " + value + " decayLast: "+ HerculesRMX.decayLast);
- if (HerculesRMX.scratchMode) { // do some scratching
+ if (HerculesRMX.scratching) {
+ var currentDate = new Date().getTime();
+ if (HerculesRMX.debug) print(currentDate);
+ if (currentDate > HerculesRMX.decayLast + HerculesRMX.decayInterval) {
+ HerculesRMX.decayLast = currentDate;
+ if (HerculesRMX.debug) print(" new playposition: " + value + " decayLast: "+ HerculesRMX.decayLast);
if (HerculesRMX.debug) print("Scratch deck1: " + engine.getValue("[Channel1]","scratch") + " deck2: "+ engine.getValue("[Channel2]","scratch"));
- // print("do scratching " + jogValue);
- // engine.setValue(group,"scratch", jogValue); // /64);
-
- var jog1DecayRate = HerculesRMX.decayRate * (engine.getValue("[Channel1]","play") ? 1 : 5);
+ var jog1DecayRate = HerculesRMX.decayRate * (engine.getValue("[Channel1]","play") ? 1 : 3);
var jog1 = engine.getValue("[Channel1]","scratch");
- if (jog1 != 0) {
- if (Math.abs(jog1) > jog1DecayRate) {
+ if (jog1 != 0) {
+ if (Math.abs(jog1) > jog1DecayRate) {
engine.setValue("[Channel1]","scratch", (jog1 / jog1DecayRate).toFixed(2));
} else {
engine.setValue("[Channel1]","scratch", 0);
}
}
- var jog2DecayRate = HerculesRMX.decayRate * (engine.getValue("[Channel2]","play") ? 1 : 5);
+ var jog2DecayRate = HerculesRMX.decayRate * (engine.getValue("[Channel2]","play") ? 1 : 3);
var jog2 = engine.getValue("[Channel2]","scratch");
- if (jog2 != 0) {
- if (Math.abs(jog2) > jog2DecayRate) {
- engine.setValue("[Channel2]","scratch", (jog2 / jog2DecayRate).toFixed(2));
- } else {
- engine.setValue("[Channel2]","scratch", 0);
- }
- }
+ if (jog2 != 0) {
+ if (Math.abs(jog2) > jog2DecayRate) {
+ engine.setValue("[Channel2]","scratch", (jog2 / jog2DecayRate).toFixed(2));
+ } else {
+ engine.setValue("[Channel2]","scratch", 0);
+ }
+ }
+ if (engine.getValue("[Channel1]","scratch") == 0 && engine.getValue("[Channel1]","scratch") == 0) {
+ HerculesRMX.scratching = false;
+ // engine.stopTimer(HerculesRMX.scratchTimer);
+ // HerculesRMX.scratchTimer = 0;
+ }
}
- }
+ }
+}
+
+//Rate change event handler to reset sync and reset leds
+HerculesRMX.rateChange = function (value, group) {
+ if (!HerculesRMX.syncing) {
+ midi.sendShortMsg(0xB0, HerculesRMX.leds["[Channel1] beatsync"], HerculesRMX.ledOff);
+ midi.sendShortMsg(0xB0, HerculesRMX.leds["[Channel2] beatsync"], HerculesRMX.ledOff);
+ }
+ if (value != 0) {
+ midi.sendShortMsg(0xB0, HerculesRMX.leds[group + " pitchreset"], HerculesRMX.ledOff);
+ }
+ HerculesRMX.syncing = false;
}
HerculesRMX.shutdown = function(id) {
}
-HerculesRMX.getGroup = function (control){
-// get the "group" that used to be provided in group, this is not reusable across devices
-// and also breaks remapping of these functions to other buttons.
- var controlToGroup = {
- 0x2F:"[Channel1]",
- 0x30:"[Channel2]",
- 0x0C:"[Channel1]", // Cue
- 0x24:"[Channel2]",
- 0x0B:"[Channel1]", // Play
- 0x23:"[Channel2]",
- 0x0D:"[Channel1]", // Stop
- 0x25:"[Channel2]",
- 0x12:"[Channel1]", // Load Deck
- 0x16:"[Channel2]",
- 0x2F:"[Channel1]", // Jog Wheels
- 0x30:"[Channel2]"
- }
- return controlToGroup[control];
-}
-
-
HerculesRMX.toggle_scratch_mode = function (channel, control, value, status) {
if (value > 0) {
HerculesRMX.scratchMode = !HerculesRMX.scratchMode;
@@ -102,8 +100,7 @@
}
}
-HerculesRMX.stop_and_reset_track = function (channel, control, value, status) {
- var group = HerculesRMX.getGroup(control);
+HerculesRMX.stop_and_reset_track = function (channel, control, value, status, group) {
if (engine.getValue(group, "duration") == 0) { if (value) print("No song on " + group); return; };
if (value > 0) {
engine.setValue(group,"cue_default",0);
@@ -116,41 +113,50 @@
}
}
-HerculesRMX.up_down_arrows = function (channel, control, value, status) {
- // TODO replace with two seperate functions (Next/Prev) to make them distinctly rebindable.
- HerculesRMX.playlistJogScrollMode = value > 0;
- if (value > 0) {
- switch (control) {
- case 0x2A: engine.setValue("[Playlist]","SelectPrevTrack", (value > 0)); break;
- case 0x2B: engine.setValue("[Playlist]","SelectNextTrack", (value > 0)); break;
- }
+HerculesRMX.next = function (channel, control, value, status) {
+ HerculesRMX.playlistJogScrollMode = value > 0;
+ if (value > 0) {
+ engine.setValue("[Playlist]","SelectNextTrack", (value > 0));
+ }
+}
+
+HerculesRMX.prev = function (channel, control, value, status) {
+ HerculesRMX.playlistJogScrollMode = value > 0;
+ if (value > 0) {
+ engine.setValue("[Playlist]","SelectPrevTrack", (value > 0));
}
}
-HerculesRMX.jog_wheel = function (channel, control, value, status) {
+HerculesRMX.jog_wheel = function (channel, control, value, status, group) {
// 7F > 40: CCW Slow > Fast - 127 > 64
// 01 > 3F: CW Slow > Fast - 0 > 63
- var group = HerculesRMX.getGroup(control);
// print ("Wheel");
// script.debug(group, control, value, status);
var jogValue = value >=0x40 ? value - 0x80 : value; // -64 to +63, - = CCW, + = CW
if (HerculesRMX.playlistJogScrollMode) { // zip through library quickly
- engine.setValue("[Playlist]","SelectTrackKnob", jogValue);
+ if (jogValue > 0) {
+ engine.setValue("[Playlist]","SelectNextTrack", 1);
+ } else if (jogValue < 0) {
+ engine.setValue("[Playlist]","SelectPrevTrack", 1);
+ }
} else if (HerculesRMX.scratchMode) { // do some scratching
if (HerculesRMX.debug) print("do scratching value:" + value + " jogValue: " + jogValue );
- // engine.setValue(group,"scratch", engine.getValue(group,"scratch") + (jogValue/64));
- engine.setValue(group,"scratch", (engine.getValue(group,"scratch") + (jogValue/64)).toFixed(2));
+ engine.setValue(group,"scratch", jogValue);
+ //if (!HerculesRMX.scratchTimer) {
+ if (!HerculesRMX.scratching) {
+ //HerculesRMX.scratchTimer = engine.beginTimer(HerculesRMX.decayInterval, "HerculesRMX.wheelDecay", false);
+ HerculesRMX.scratching = true;
+ //print("Started timer with id: " + HerculesRMX.scratchTimer);
+ }
} else { // do pitch adjustment
- var newValue = jogValue; //(engine.getValue(group,"wheel") + (jogValue/5)).toFixed(2);
-// if (newValue > 127) { newValue = 127; }
+ var newValue = jogValue * (engine.getValue(group,"play") ? 1 : 10);
if (HerculesRMX.debug) print("do pitching adjust " + jogValue + " new Value: " + newValue);
engine.setValue(group,"jog", newValue);
}
}
-HerculesRMX.cue = function (channel, control, value, status) {
- var group = HerculesRMX.getGroup(control);
+HerculesRMX.cue = function (channel, control, value, status, group) {
if (engine.getValue(group, "duration") == 0) { if (value) print("No song on " + group); return; };
if (value) { // Down
@@ -161,9 +167,8 @@
} else { // Release
if (HerculesRMX.debug) print("R. Play: " + engine.getValue(group,"play") + " PlayPosition: " + engine.getValue(group,"playposition") + " cue_default: "+ engine.getValue(group,"cue_default"));
- if (HerculesRMX.cuePlay[group]) {
-// engine.setValue(group,"cue_default",0);
- engine.setValue(group,"play",1);
+ if (HerculesRMX.cueButton[group]) {
+ engine.setValue(group,"cue_default",0);
}
midi.sendShortMsg(0xB0, HerculesRMX.leds[group + " cue"], HerculesRMX.ledOff);
HerculesRMX.cuePlay[group] = false;
@@ -171,9 +176,25 @@
}
}
-HerculesRMX.play = function (channel, control, value, status) {
+
+
+HerculesRMX.beatSync = function (channel, control, value, status, group) {
+ if (value) {
+ HerculesRMX.syncing = true;
+ engine.setValue(group,"beatsync",0);
+ midi.sendShortMsg(0xB0, control, HerculesRMX.ledOn);
+ }
+}
+
+HerculesRMX.rateReset = function (channel, control, value, status, group) {
+ if (value) {
+ engine.setValue(group,"rate",0);
+ midi.sendShortMsg(0xB0, control, HerculesRMX.ledOn);
+ }
+}
+
+HerculesRMX.play = function (channel, control, value, status, group) {
// Only send events when play is pushed, not when it comes back up.
- var group = HerculesRMX.getGroup(control);
if (engine.getValue(group, "duration") == 0) { if (value) print("No song on " + group); return; };
if (value) {
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel