Hello,
While working on my Denon MC7000 monster controller mapping, I’ve defined a secondary/custom SHIFT+ key, and that suddenly opened up a VAST field of available buttons for extra control mappings. For many buttons, it was straight forward just press the custom SHIFT and the button, and voila - one more layer of control options is suddenly becoming available.
In the case of MC7000, we have a pair of buttons on both sides that are for controlling the Views in Serato. I chose the L.PREP button as “Controller Shift Key”, and now DJ allows me to overmap ANY (almost) button on the controller with an additional command, on top of the built-in Shift button, which in my case makes the controller itself to send different message than the No-Shift state.
For most buttons, it was straight forward to make the custom Shift actions. But not for all. Examples are the Pad Modes. The Pads send the same MIDI message, so the app evaluates the selected PadMode, when performing actions in the context of Cue/Loop/Slicer/Sampler and their extra sub modes. So in my case, mapping the Pads was limited to only one extra command with the Custom SHIFT key by default. But I wasn’t happy with this. I want to overmap more pads and use extra functions in the context of the different pad modes.
Another example is the FX controll buttons/knobs/rotaries. MC7000 is designed for Serato primarily, and (at that time) Serato has only 2FX units, assignable to the 4 decks.In Djay, we have FX unit bound to each of the decks, so I need to be able to separately control 4 FX units, while the controller is sending unique messages for only two FX units. Yet, Djay is able to independently control 4FX units. They somehow do it.
So I started to reverse engineer the way Algoriddim is doing their mappings and how they implement the separation of the Pad Modes, doing different stuff in the context of the selected PadMode, and how we can control 4FX slots, while the controller is sending unique messages for only 2.
The great news is that Djay has “modifiers” built in. They are not exposed for the users to mess with them in the UI, but are there, and freely available to use as conditions, given that the user is brave enough to mess with the XML (fairly simple job, with a moderate risk though).
Following my work on the XML and the good progress that I did with the MC7000 mapping, I want to share my Know How, and allow others to benefit from the available modifiers work there is. I’ve also created an enhancement request to expose the XML “condition” string in the UI, so we don’t need to mess with the XML and get the needed context filtering right from the UI
So here is what I found:
- The Pad Modes are stored in 4 modifiers - one for each of the decks. Here is an example:
<key>condition</key>
<string>modifier2 == 13</string>
<key>keyPath</key>
<string>turntable2.clearSavedLoop8</string>
modifier2 sits for deck2 Pad Mode state flag.
The value “13” is the “Pad Mode Saved Loop”
The Command that the button does in the mapping is “turntable2.clearSavedLoop8” to clear the Saved Loop at Slot 8 on Deck2. Simple.
Another example is the Cue Points control:
<key>condition</key>
<string>modifier1 == 0</string>
<key>keyPath</key>
<string>turntable1.clearCuePoint3</string>
modifier1 holds the pad mode state for Deck1 and the “0” is Pad Mode “Cue”. The quoted action is to clearCuePoint3 on Deck1 (turntable1).
Bellow is the list of the modifiers and their values known to me at this point:
- modifier1-4 == 0 - Pad Mode Hot Cue
- modifier1-4 == 2 - unclear. there are empty definitions in the mapping to set pad colors, but no commands.
- modifier1-4 == 3 - Pad Mode Cue Loop
- modifier1-4 == 7 - Pad Mode Bounce Loop a.k.a Loop Roll
- modifier1-4 == 9 - Pad Mode Slicer
- modifier1-4 == 10 - Pad Mode Slicer Loop
- modifier1-4 == 11 - Pad Mode Sampler
- modifier1-4 == 12 - Pad Mode Sampler - maybe one of them is velocity sensitive, I don’t know. They seem to invoke the same action
- modifier1-4 == 13 - Pad Mode Saved Loop
- modifier1-4 == 15 - unclear - there are empty definitions in the mapping to set pad colors, but no commands.
- modifier5 == 0 - Deck1 selected
- modifier5 == 1 - Deck3 selected
- modifier6 == 0 - Deck2 selected
- modifier6 == 1 - Deck4 selected
And I have no clue what the values for these PadModes are:
- Pad Mode Auto Loop - modifier1-4 == ?
- Pad Mode Manual Loop - modifier1-4 == ?
- Pad Mode Skipping - modifier1-4 == ?
- Pad Mode Instant FX - modifier1-4 ==
- Pad Mode Neural Mix - modifier1-4 == ?
- Pad Mode Looper - modifier1-4 ==
- Pad Mode User1 - modifier1-4 == ?
- Pad Mode User2 - modifier1-4 == ?
- Pad Mode User3 - modifier1-4 == ?
- Pad Mode User4 - modifier1-4 == ?
- Pad Mode Empty - modifier1-4 == ?
I guess you start seeing the picture now. Please note that I’m not sure if the PadMode values are common for all controllers. I suspect they are, and there’s a well thought-out convention for modifiers and their states that the Algoriddim Dev & Controller Mapping Teams are using, but that’s just a guess. Perhaps there will be an official public document at some future point describing this. For now, I can only explain what I’ve concluded by my mapping efforts. Further to that, it appears that windows mapping for MC7000 is in JSON, not XML. There’s not a big diff between XML & JSON, and both do the same, but apparently Djay knows JSON too.
Another goal that I’ve had was to map the FX Slot ON/Off buttons for assigning NM effects. NM effects are assignable in the 3 way mode only - Drums/Harmonics/Accapella. MC7000 has 3FX knobs with On/Off buttons underneath, so I want the buttons to set C.SHIFT+FX1->Drums; C.SHIFT+FX2->Harmonics; C.SHIFT+FX3->Vocals. By default, it worked well but only for Deck 1 & 2. As explained above, Serato has only 2FX units, and Denon made the 7K sending unique MIDI messages for only 2 FX control units. I needed to have separate control over Deck 3&4, and that wasn’t possible out of the box.
So I opened up the XML, and figured out that switching from Deck 1 to 3 is tracked in “modifier5” as:
<key>condition</key>
<string>modifier5 == 0</string>
<key>condition</key>
<string>modifier5 == 1</string>
The value “0” stands for Deck 1 active on the controller, the value “1” stands for Deck 3 active on the controller.
Respectively, Decks 2/4 are tracked in modifier6 as 0 for Deck2 and 1 for Deck4
<key>condition</key>
<string>modifier6 == 0</string>
<key>condition</key>
<string>modifier6 == 1</string>
You can probably get the picture now.
So HOWTO map it and navigate in this mess (TODO: Create screenshots for easier understanding).
First step:
- Choose a Custom Shift buttom. I chose the L.PREP button to be my Custom Shift button. It has to be Unassigned from Any other action than acting as a “Controller Shift Key” in the “General” mapping target. I will now refer to Custom Shift as the LP button.
- Keep the LP pressed (as if a SHIFT), and press any other key on the controller. For example, I’m pressing Deck1->FX1->ON button. This creates a new entry in the mapping table, in my case it’s “NOTE C-1 (SHIFT)” with empty action.
- Now just map the message “NOTE C-1 (SHIFT)” to do something. I did “Deck1” → “FX1 Assignment Drums”.
I now have a 3rd action assigned to FX1 On/Off. The default is FX1 ON/OFF; the Built-in Shift performs “FX1 Select Next”, and now the LP (Custom Shift) does “FX1 Assignment Drums”. Wow. that’s just great. But it’s only for Deck1. It wouldn’t work if I switch to Deck3 on the controller, as the MIDI message of FX1/2 doesn’t take into account if Deck 1 or 3 is selected. It’s always the same. So I banged my head a little, and decided to do this research and figure out how the Djay team is handling it for the FX controls mapping - they have the same issue, and have made it to work right for Decks 1/3 & 2/4. So I did what they do:
-
Now that you have the mapping for “Deck1” → “FX1 Assignment Drums”, Duplicate it. On the Duplicate, change the Deck to “Deck3”. Now, when you press the FX1 ON button, it will assign the NM Drums channel to both Deck 1 and Deck 3. Not ideal, for sure - I want Dry signal on the Deck1 Drums, and wet on the Deck3 Drums.
-
Get & Open the XML of the mapping and search for “turntable1.fx1RoutingInstrumental”. In my case it looks like this
<dict>
<key>keyPath</key>
<string>turntable1.fx1RoutingInstrumental</string>
<key>midiChannel</key>
<integer>8</integer>
.... other tags....
</dict>
As you can see there is no “condition” tag in here. The command is executed unconditionally, every time the button is pressed. Because we’ve created Duplicate entry to handle Deck3, we should also have the same section, but for the other deck (turntable3)
<dict>
<key>keyPath</key>
<string>turntable3.fx1RoutingInstrumental</string>
<key>midiChannel</key>
<integer>8</integer>
.... other tags....
</dict>
Once you’ve located them,
- For “turntable1” add the set of “condition” lines, bellow the “dict” tag, so the entry will look like.
<dict>
<key>condition</key>
<string>modifier5 == 0</string>
<key>keyPath</key>
<string>turntable1.fx1RoutingInstrumental</string>
<key>midiChannel</key>
<integer>8</integer>
.... other tags....
</dict>
And for Deck3, it’s the same, but with “modifier5” value of “1”
<dict>
<key>condition</key>
<string>modifier5 == 1</string>
<key>keyPath</key>
<string>turntable3.fx1RoutingInstrumental</string>
<key>midiChannel</key>
<integer>8</integer>
.... other tags....
</dict>
-
Save and put the modified XML mapping file back in place. (TODO: Add backup instructions, how to do it on iOS, default locations of the files etc.)
You need to restart the app to reload the new mapping XML from the file - this restart applies to iOS, MacOS, Windows. -
It’s done - now Deck 1 & Deck 3 will have independent management of the FX1 Slot assignment - be in on the Deck, or the Drums NM channel.
-
The same approach is applicable to everything else.
a. Hit the Custom Shift + the button and set a mapping command
b. Duplicate it as needed (either FX units or Pad Modes, whatever you need)
c. Edit the XML, insert the “condition section” where appropriate
d. Put the XML back in place, restart the app and enjoy!
I’m very excited about it, and wanted to describe it quickly, so other can benefit and enjoy from it too. There’s some more work to make this a propper manual/HOWTO, and I’ve left few “TODO” sections here and there. This deserves screenshots, per-platform instructions, etc. Probably clarity of the description too. Yet, hopefully, this is already clear enough and this knowledge and instructions will already be useful to others too.
Happy Mapping!