{"action":"created","comment":{"url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/comments/216150587","pull_request_review_id":153574937,"id":216150587,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNjE1MDU4Nw==","diff_hunk":"@@ -1,95 +1,830 @@\n-/* ╔══:::Made Lovingly By Circuitfry:::═════════════════════════════════╗\n- * ║     Hercules DJConsole RMX 2 Mapping Scripts                       ║\n- * ╚════════════════════════════════════════════════════════════════════╝\n- */\n-\n-function DJCRMX2() {}\n-DJCRMX2.decks = [];\n-\n-/* [ Function init ]\n- * Initiates some global variables and assigns an ID. Required.\n- */\n-DJCRMX2.init = function (id) {\n+////////////////////////////////////////////////////////////////////////\n+// JSHint configuration                                               //\n+////////////////////////////////////////////////////////////////////////\n+/* global engine                                                      */\n+/* global script                                                      */\n+/* global midi                                                        */\n+/* global components                                                  */\n+////////////////////////////////////////////////////////////////////////\n+var DJCRMX2 = {};\n+\n+/*\n+\tAuthor: \t\tDJMaxergy\n+\tVersion: \t\t1.00, 06/21/2018\n+\tDescription: \tHercules DJ Console RMX 2 Mapping for Mixxx\n+    Source: \t\thttp://github.com/DJMaxergy/mixxx/tree/herculesDJConsoleRMX2mapping_overhaul\n+    \n+    Copyright (c) 2018 DJMaxergy, licensed under GPL version 2 or later\n+    Copyright (c) 2016 Circuitfry, base for this mapping\n+    \n+    Contributors:\n+    - Circuitfry: initial Hercules DJ Console RMX 2 mapping\n+      \n+    GPL license notice for current version:\n+    This program is free software; you can redistribute it and/or modify it under the terms of the\n+    GNU General Public License as published by the Free Software Foundation; either version 2\n+    of the License, or (at your option) any later version.\n+    \n+    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\n+    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See\n+    the GNU General Public License for more details.\n+    \n+    You should have received a copy of the GNU General Public License along with this program; if\n+    not, write to the Free Software Foundation, Inc.,\n+    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n+    \n+    \n+    MIT License for earlier versions:\n+    Permission is hereby granted, free of charge, to any person obtaining a copy of this software\n+    and associated documentation files (the \"Software\"), to deal in the Software without\n+    restriction, including without limitation the rights to use, copy, modify, merge, publish,\n+    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the\n+    Software is furnished to do so, subject to the following conditions:\n+    \n+    The above copyright notice and this permission notice shall be included in all copies or\n+    substantial portions of the Software.\n+    \n+    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n+    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n+    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n+*/\n+\n+///////////////////////////////////////////////////////////////\n+//                       USER OPTIONS                        //\n+///////////////////////////////////////////////////////////////\n+\n+// Sets the jogwheels sensivity. 1 is default, 2 is twice as sensitive, 0.5 is half as sensitive.\n+DJCRMX2.jogwheelSensivity = 1;\n+\n+// Sets how much more sensitive the jogwheels get when holding shift.\n+// Set to 1 to disable jogwheel sensitivity increase when holding shift (default: 10).\n+DJCRMX2.jogwheelShiftMultiplier = 10;\n+\n+// If true, vu meters twinkle if AutoDJ is enabled (default: true).\n+DJCRMX2.twinkleVumeterAutodjOn = true;\n+\n+// If true, PFL / Cue (headphone) is being activated by loading a track into certain deck (default: true).\n+DJCRMX2.autoPFL = true;\n+\n+// If true, deck vu meters show master output (L = Deck A, R = Deck B).\n+// If false, deck vu meter shows deck output (mono) (default: false).\n+DJCRMX2.vuMeterOutputMaster = false;\n+\n+// If true, Samplers and EffectRack get shown or hidden in dependance of Pad-Mode (default: false).\n+DJCRMX2.showHideSamplersEffectsOnPadMode = false;\n+\n+\n+///////////////////////////////////////////////////////////////\n+//               INIT, SHUTDOWN & GLOBAL HELPER              //\n+///////////////////////////////////////////////////////////////\n+\n+DJCRMX2.flashLEDTimer = new Array(2);\n+DJCRMX2.vuMeterEnabled = [true, true];\n+\n+// PAD mode storage:\n+DJCRMX2.padModes = {\n+    'effect': 0x00,\n+    'sampler': 0x01,\n+    'cue': 0x03,\n+    'loop': 0x02\n+};\n+DJCRMX2.activePadMode = [\n+    DJCRMX2.padModes.effect,\n+    DJCRMX2.padModes.effect\n+];\n+\n+DJCRMX2.loopIntervals = [1, 2, 4, 8];\n+DJCRMX2.looprollIntervals = [1 / 16, 1 / 8, 1 / 4, 1 / 2];\n+\n+DJCRMX2.scratchSettings = {\n+    'alpha': 1.0 / 8,\n+    'beta': 1.0 / 8 / 32,\n+    'jogResolution': 256,\n+    'vinylSpeed': 33 + 1 / 3,\n+};\n+\n+DJCRMX2.channelGroupsPad = {\n+    '[Channel1]': 0x00,\n+    '[Channel2]': 0x10\n+};\n+\n+DJCRMX2.channelGroupsNonPad = {\n+    '[Channel1]': 0x00,\n+    '[Channel2]': 0x11\n+};\n+\n+DJCRMX2.padLedGroups = {\n+    'effect': 0x01,\n+    'sampler': 0x05,\n+    'cue': 0x09,\n+    'loop': 0x0D\n+};\n+\n+DJCRMX2.nonPadDeckLeds = {\n+    'play': 0x21,\n+    'cue': 0x22,\n+    'sync': 0x23,\n+    'killTreble': 0x28,\n+    'killMedium': 0x29,\n+    'killBass': 0x2A,\n+    'source': 0x2B,\n+    'preview': 0x2E,\n+    'jogWheelPressed': 0x2F\n+};\n+\n+DJCRMX2.generalLeds = {\n+    'files': 0x43,\n+    'folders': 0x44,\n+    'scratch': 0x47\n+};\n+\n+\n+DJCRMX2.init = function(id) {\n+    components.Component.prototype.shiftOffset = 0x20;\n+    components.Component.prototype.shiftChannel = true;\n+    components.Component.prototype.sendShifted = true;\n+\n     DJCRMX2.id = id;\n+    DJCRMX2.flashLEDTimer[0] = 0;\n+    DJCRMX2.flashLEDTimer[1] = 0;\n+\n+    // activate vu meter timer for Auto DJ:\n+    if (DJCRMX2.twinkleVumeterAutodjOn) {\n+        DJCRMX2.vuMeterTimer = engine.beginTimer(200, 'DJCRMX2.vuMeterTwinkle()');\n+    }\n+\n+    // init samplers:\n+    if (engine.getValue('[Master]', 'num_samplers') < 32) {\n+        engine.setValue('[Master]', 'num_samplers', 32);\n+    }\n+\n+    // assign EffectUnits:\n+    engine.setValue('[EffectRack1_EffectUnit1]', 'group_[Channel1]_enable', 1);\n+    engine.setValue('[EffectRack1_EffectUnit2]', 'group_[Channel2]_enable', 1);\n+\n+    // init decks:\n+    DJCRMX2.decks = [];\n     DJCRMX2.decks[1] = new DJCRMX2.Deck(1);\n     DJCRMX2.decks[2] = new DJCRMX2.Deck(2);\n-    engine.setValue(\"[Microphone]\", \"enabled\", 0);\n-    engine.setValue(\"[Microphone]\", \"talkover\", 0);\n-}\n+\n+    // init master section:\n+    DJCRMX2.master = new DJCRMX2.Master();\n+\n+    // init microphone section:\n+    DJCRMX2.micOnOffButton = new components.Button({\n+        group: '[Microphone]',\n+        input: function(channel, control, value, status, group) {\n+            if (value) {\n+                engine.setValue(this.group, 'enabled', 1);\n+                engine.setValue(this.group, 'talkover', 1);\n+            } else {\n+                engine.setValue(this.group, 'enabled', 0);\n+                engine.setValue(this.group, 'talkover', 0);\n+            }\n+        },\n+    });\n+\n+    // init library section:\n+    DJCRMX2.library = new DJCRMX2.Library();\n+\n+    // initiate control status request:\n+    midi.sendShortMsg(0xB0, 0x7F, 0x7F); // B0 7F xx -> any value\n+};\n+\n+DJCRMX2.shutdown = function(id) {\n+    engine.setValue('[EffectRack1_EffectUnit1]', 'group_[Channel1]_enable', 0);\n+    engine.setValue('[EffectRack1_EffectUnit2]', 'group_[Channel2]_enable', 0);\n+\n+    DJCRMX2.resetLeds();\n+};\n+\n+DJCRMX2.resetLeds = function() {\n+    var deckOffset = 0,\n+        led = 0,\n+        i = 0;\n+\n+    // non-pad deck Leds:\n+    for (deckOffset in DJCRMX2.channelGroupsNonPad) {\n+        if (DJCRMX2.channelGroupsNonPad.hasOwnProperty(deckOffset)) {\n+            for (led in DJCRMX2.nonPadDeckLeds) {\n+                if (DJCRMX2.nonPadDeckLeds.hasOwnProperty(led)) {\n+                    midi.sendShortMsg(0x90, DJCRMX2.nonPadDeckLeds[led] + DJCRMX2.channelGroupsNonPad[deckOffset], 0);\n+                }\n+            }\n+        }\n+    }\n+    // pad deck Leds:\n+    for (deckOffset in DJCRMX2.channelGroupsPad) {\n+        if (DJCRMX2.channelGroupsPad.hasOwnProperty(deckOffset)) {\n+            for (led in DJCRMX2.padLedGroups) {\n+                if (DJCRMX2.padLedGroups.hasOwnProperty(led)) {\n+                    for (i = 0; i < 4; i++) {\n+                        midi.sendShortMsg(0x90, DJCRMX2.padLedGroups[led] + DJCRMX2.channelGroupsPad[deckOffset] + i, 0);\n+                        midi.sendShortMsg(0xB0, DJCRMX2.padLedGroups[led] + DJCRMX2.channelGroupsPad[deckOffset] + i, 0);\n+                    }\n+                }\n+            }\n+        }\n+    }\n+    // general Leds:\n+    for (led in DJCRMX2.generalLeds) {\n+        if (DJCRMX2.generalLeds.hasOwnProperty(led)) {\n+            midi.sendShortMsg(0x90, DJCRMX2.generalLeds[led], 0);\n+        }\n+    }\n+    //VU meter Leds:\n+    for (i = 0; i < 12; i++) {\n+        midi.sendShortMsg(0x90, 0x49 + i, 0);\n+    }\n+};\n+\n+///////////////////////////////////////////////////////////////\n+//                      SYSEX HANDLER                        //\n+///////////////////////////////////////////////////////////////\n+DJCRMX2.inboundSysex = function(data, length) {\n+    //[F0 00 01 4E 0E 06 0E 00 00 00 00 00 00 00 F7] Channel 1 Effect Mode\n+    //[F0 00 01 4E 0E 06 0E 00 00 00 01 00 00 00 F7] Channel 1 Sampler Mode\n+    //[F0 00 01 4E 0E 06 0E 00 00 00 03 00 00 00 F7] Channel 1 Cue Mode\n+    //[F0 00 01 4E 0E 06 0E 00 00 00 02 00 00 00 F7] Channel 1 Loop Mode\n+    //[F0 00 01 4E 0E 06 0E 00 01 00 00 00 00 00 F7] Channel 2 Effect Mode\n+    //[F0 00 01 4E 0E 06 0E 00 01 00 01 00 00 00 F7] Channel 2 Sampler Mode\n+    //[F0 00 01 4E 0E 06 0E 00 01 00 03 00 00 00 F7] Channel 2 Cue Mode\n+    //[F0 00 01 4E 0E 06 0E 00 01 00 02 00 00 00 F7] Channel 2 Loop Mode\n+    //[F0 00 01 4E 0E 06 02 00 00 00 01 00 00 00 F7] Channel 1 Shift press\n+    //[F0 00 01 4E 0E 06 02 00 00 00 00 00 00 00 F7] Channel 1 Shift release\n+    //[F0 00 01 4E 0E 06 02 00 01 00 01 00 00 00 F7] Channel 2 Shift press\n+    //[F0 00 01 4E 0E 06 02 00 01 00 00 00 00 00 F7] Channel 2 Shift release\n+    var typeIndex = data[6], //Mode = 0x0E, Shift = 0x02\n+        deckIndex = data[8], //Deck 1 = 0x00, Deck 2 = 0x01\n+        padModeIndex = data[10]; //Effect = 0x00, Sampler = 0x01, Cue = 0x03, Loop = 0x02\n+\n+    if (length > 10 && typeIndex === 0x0E) {\n+        if (deckIndex < 0x02 && deckIndex >= 0x00) {\n+            if (padModeIndex < 0x04 && padModeIndex >= 0x00) {\n+                DJCRMX2.activePadMode[deckIndex] = padModeIndex;\n+                DJCRMX2.onPadModeChanged(deckIndex);\n+            }\n+        }\n+    }\n+};\n+\n+DJCRMX2.onPadModeChanged = function(index) {\n+    var nonActiveIndex = index ? 0 : 1,\n+        showSamplers = true,\n+        showEffectRack = true;\n+\n+    if (DJCRMX2.activePadMode[index] === DJCRMX2.padModes.effect) {\n+        if (DJCRMX2.activePadMode[nonActiveIndex] !== DJCRMX2.padModes.sampler) {\n+            showSamplers = false;\n+        }\n+        showEffectRack = true;\n+    } else if (DJCRMX2.activePadMode[index] === DJCRMX2.padModes.sampler) {\n+        showSamplers = true;\n+        if (DJCRMX2.activePadMode[nonActiveIndex] !== DJCRMX2.padModes.effect) {\n+            showEffectRack = false;\n+        }\n+    } else if (DJCRMX2.activePadMode[index] === DJCRMX2.padModes.cue ||\n+        DJCRMX2.activePadMode[index] === DJCRMX2.padModes.loop) {\n+        if (DJCRMX2.activePadMode[nonActiveIndex] !== DJCRMX2.padModes.sampler) {\n+            showSamplers = false;\n+        }\n+        if (DJCRMX2.activePadMode[nonActiveIndex] !== DJCRMX2.padModes.effect) {\n+            showEffectRack = false;\n+        }\n+    }\n+\n+    if (DJCRMX2.showHideSamplersEffectsOnPadMode) {\n+        engine.setValue('[Samplers]', 'show_samplers', showSamplers ? 1 : 0);\n+        engine.setValue('[EffectRack1]', 'show', showEffectRack ? 1 : 0);\n+    }\n+};\n+\n+\n+///////////////////////////////////////////////////////////////\n+//                   HELPER FUNCTIONS                        //\n+///////////////////////////////////////////////////////////////\n+DJCRMX2.doNavigate = function(direction) {\n+    engine.setValue('[Library]', 'MoveVertical', direction);\n+};\n+\n+DJCRMX2.getRotaryDelta = function(value) {\n+    var delta = 0x40 - Math.abs(0x40 - value),\n+        isCounterClockwise = value > 0x40;\n+\n+    if (isCounterClockwise) {\n+        delta *= -1;\n+    }\n+    return delta;\n+};\n+\n+\n+///////////////////////////////////////////////////////////////\n+//                   FLASH LED HANDLER                       //\n+///////////////////////////////////////////////////////////////\n+DJCRMX2.flashLEDState = false;\n+DJCRMX2.flashLEDHandler = function(channelGroup, padGroup, index) {\n+    var midiChannel = DJCRMX2.channelGroupsPad[channelGroup] + DJCRMX2.padLedGroups[padGroup] + index;\n+\n+    DJCRMX2.flashLEDState = !DJCRMX2.flashLEDState;\n+    midi.sendShortMsg(0x90, midiChannel, DJCRMX2.flashLEDState ? 0x7F : 0x00);\n+};\n+\n+\n+///////////////////////////////////////////////////////////////\n+//                      VU - METER                           //\n+///////////////////////////////////////////////////////////////\n+\n+DJCRMX2.vuMeterTwinkle = function() {\n+    if (engine.getValue('[AutoDJ]', 'enabled')) {\n+        DJCRMX2.vuMeterEnabled[0] = !DJCRMX2.vuMeterEnabled[0];\n+        DJCRMX2.vuMeterEnabled[1] = !DJCRMX2.vuMeterEnabled[1];\n+    }\n+};\n+\n+DJCRMX2.vuMeterLeds = function(value, group, control) {\n+    var midiOut = 0,\n+        stepSize = 1 / 5,\n+        deckOffset = [0x49, 0x4F],\n+        deck = 0,\n+        peakMidiOut = engine.getValue(group, 'PeakIndicator') ? 0x7F : 0x00;\n+\n+    if (DJCRMX2.vuMeterOutputMaster) {\n+        if (control === 'VuMeterL') {\n+            deck = 1;\n+        }\n+        if (control === 'VuMeterR') {\n+            deck = 2;\n+        }\n+    } else {\n+        deck = group.match(/\\d+/)[0];\n+    }\n+\n+    for (var i = 0; i < 5; i++) {\n+        if (value > ((i + 0.1) * stepSize)) {\n+            midiOut = 0x7F;\n+        } else {\n+            midiOut = 0x00;\n+        }\n+        if (DJCRMX2.twinkleVumeterAutodjOn && engine.getValue('[AutoDJ]', 'enabled')) {\n+            if (DJCRMX2.vuMeterEnabled[deck - 1]) {\n+                midiOut = 0x00;\n+            }\n+        }\n+        midi.sendShortMsg(0x90, i + deckOffset[deck - 1], midiOut);\n+    }\n+    midi.sendShortMsg(0x90, 0x05 + deckOffset[deck - 1], peakMidiOut);\n+};\n+\n \n ////////////////////////////////////////////////////////////////////////\n-// Decks                                                              //\n+//                             DECKS                                  //\n ////////////////////////////////////////////////////////////////////////\n \n-DJCRMX2.Deck = function(number) {\n-    this.number = number;\n-    this.group = \"[Channel\" + this.number + \"]\";\n-    this.scratchTimer = 0;\n+DJCRMX2.Deck = function(deckNumbers, channel) {\n+    components.Deck.call(this, deckNumbers);\n+\n+    var theDeck = this;\n+    theDeck.samplerBankIndex = 0;\n+\n+    // save set up speed slider range from the Mixxx settings:\n+    theDeck.setUpSpeedSliderRange = engine.getValue(this.currentDeck, 'rateRange');\n+\n+    this.shiftButton = function(channel, control, value, status, group) {\n+        if (value === 0x7F) {\n+            this.shift();\n+        } else {\n+            this.unshift();\n+        }\n+    };\n+\n+    this.playButton = new components.PlayButton([0x90, DJCRMX2.nonPadDeckLeds.play + DJCRMX2.channelGroupsNonPad[this.currentDeck]]);\n+    this.cueButton = new components.CueButton([0x90, DJCRMX2.nonPadDeckLeds.cue + DJCRMX2.channelGroupsNonPad[this.currentDeck]]);\n+    this.syncButton = new components.SyncButton([0x90, DJCRMX2.nonPadDeckLeds.sync + DJCRMX2.channelGroupsNonPad[this.currentDeck]]);\n+\n+    this.pflButton = new components.Button({\n+        midi: [0x90, DJCRMX2.nonPadDeckLeds.preview + DJCRMX2.channelGroupsNonPad[this.currentDeck]],\n+        type: components.Button.prototype.types.toggle,\n+        unshift: function() {\n+            this.inKey = 'pfl';\n+            this.outKey = 'pfl';\n+            this.disconnect();\n+            this.connect();\n+            this.trigger();\n+        },\n+        shift: function() {\n+            this.inKey = 'keylock';\n+            this.outKey = 'keylock';\n+            this.disconnect();\n+            this.connect();\n+            this.trigger();\n+        },\n+    });\n+\n+    this.sourceButton = new components.Button({\n+        midi: [0x90, DJCRMX2.nonPadDeckLeds.source + DJCRMX2.channelGroupsNonPad[this.currentDeck]],\n+        key: 'passthrough',\n+        type: components.Button.prototype.types.toggle,\n+    });\n+\n+    this.loadButton = new components.Button({\n+        unshift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                if (value === 0x7F) {\n+                    engine.setValue(this.group, 'LoadSelectedTrack', true);\n+                    if (DJCRMX2.autoPFL) {\n+                        engine.setValue(this.group, 'pfl', true);\n+                        if (this.group === '[Channel1]') {\n+                            engine.setValue('[Channel2]', 'pfl', false);\n+                        } else if (this.group === '[Channel2]') {\n+                            engine.setValue('[Channel1]', 'pfl', false);\n+                        }\n+                    }\n+                }\n+            };\n+        },\n+        shift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                engine.setValue(this.group, 'eject', value ? 1 : 0);\n+                if (value === 0x7F && DJCRMX2.autoPFL) {\n+                    engine.setValue(this.group, 'pfl', false);\n+                }\n+            };\n+        },\n+    });\n+\n+    this.ffButton = new components.Button({\n+        number: deckNumbers,\n+        unshift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                engine.setValue(this.group, 'fwd', value);\n+            };\n+        },\n+        shift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                if (value === 0x7F) {\n+                    engine.brake(this.number, 1);\n+                }\n+            };\n+        },\n+    });\n+\n+    this.rwButton = new components.Button({\n+        number: deckNumbers,\n+        unshift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                engine.setValue(this.group, 'back', value);\n+            };\n+        },\n+        shift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                if (value === 0x7F) {\n+                    engine.spinback(this.number, 1);\n+                }\n+            };\n+        },\n+    });\n+\n+    this.pitchBendIncrButton = new components.Button({\n+        number: deckNumbers,\n+        unshift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                engine.setValue(this.group, 'rate_temp_up', value);\n+            };\n+        },\n+        shift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                var range = engine.getValue(this.group, 'rateRange');\n+\n+                if ((range * 2) > 0.90) {\n+                    range = 0.90;\n+                } else {\n+                    range = range * 2;\n+                }\n+\n+                if (value === 0x7F) {\n+                    engine.setValue(this.group, 'rateRange', range);\n+                }\n+            };\n+        },\n+    });\n+\n+    this.pitchBendDecrButton = new components.Button({\n+        number: deckNumbers,\n+        unshift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                engine.setValue(this.group, 'rate_temp_down', value);\n+            };\n+        },\n+        shift: function() {\n+            this.input = function(channel, control, value, status, group) {\n+                var range = engine.getValue(this.group, 'rateRange');\n+\n+                if ((range / 2) < theDeck.setUpSpeedSliderRange) {\n+                    range = theDeck.setUpSpeedSliderRange;\n+                } else {\n+                    range = range / 2;\n+                }\n+\n+                if (value === 0x7F) {\n+                    engine.setValue(this.group, 'rateRange', range);\n+                }\n+            };\n+        },\n+    });\n+\n+    this.loopButtons = [];\n+    this.samplerButtons = [];\n+    this.hotcueButtons = [];\n+    for (var i = 1; i <= 4; i++) {\n+        this.loopButtons[i] = new components.Button({\n+            group: this.currentDeck,\n+            number: i,\n+            unshift: function() {\n+                if (this.number === 1) {\n+                    this.input = function(channel, control, value, status, group) {\n+                        if (value === 0x7F) {\n+                            if (engine.getValue(this.group, 'loop_enabled')) {\n+                                engine.setValue(this.group, 'reloop_toggle', true);\n+                                engine.setValue(this.group, 'reloop_toggle', false);\n+                            } else {\n+                                engine.setValue(this.group, 'beatloop_activate', true);\n+                                engine.setValue(this.group, 'beatloop_activate', false);\n+                            }\n+                        }\n+                    };\n+                    this.outKey = 'loop_enabled';\n+                } else {\n+                    this.inKey = 'beatloop_' + DJCRMX2.loopIntervals[this.number - 1] + '_toggle';\n+                    this.outKey = 'beatloop_' + DJCRMX2.loopIntervals[this.number - 1] + '_enabled';\n+                }\n+                this.midi = [0x90, DJCRMX2.padLedGroups.loop + DJCRMX2.channelGroupsPad[this.group] + this.number - 1];\n+                this.disconnect();\n+                this.connect();\n+            },\n+            shift: function() {\n+                if (this.number === 1) {\n+                    this.input = function(channel, control, value, status, group) {\n+                        engine.setValue(this.group, 'beatlooproll_' + DJCRMX2.looprollIntervals[this.number - 1] + '_activate', value);\n+                    };\n+                    this.outKey = 'beatlooproll_' + DJCRMX2.looprollIntervals[this.number - 1] + '_activate';\n+                } else {\n+                    this.inKey = 'beatlooproll_' + DJCRMX2.looprollIntervals[this.number - 1] + '_activate';\n+                    this.outKey = 'beatlooproll_' + DJCRMX2.looprollIntervals[this.number - 1] + '_activate';\n+                }\n+                this.midi = [0xB0, DJCRMX2.padLedGroups.loop + DJCRMX2.channelGroupsPad[this.group] + this.number - 1];\n+                this.disconnect();\n+                this.connect();\n+            },\n+        });\n+\n+        this.samplerButtons[i] = new components.SamplerButton({\n+            number: i,\n+            midi: [0x90, DJCRMX2.padLedGroups.sampler + DJCRMX2.channelGroupsPad[this.currentDeck] + i - 1],\n+            playing: 0x00,\n+            loaded: 0x7F,\n+            empty: 0x00,\n+            unshift: function() {\n+                this.input = function(channel, control, value, status, group) {\n+                    if (this.isPress(channel, control, value, status)) {\n+                        if (engine.getValue(this.group, 'track_loaded') === 0) {\n+                            engine.setValue(this.group, 'LoadSelectedTrack', 1);\n+                        } else {\n+                            engine.setValue(this.group, 'cue_gotoandplay', 1);\n+                            engine.setParameter(this.group, 'volume', value / 0x7F);\n+                        }\n+                    }\n+                };\n+            },\n+            shift: function() {\n+                this.blockSamplerPad = false;\n+                this.input = function(channel, control, value, status, group) {\n+                    if (value === 0x00) {\n+                        this.blockSamplerPad = false;\n+                    }\n+                    if (this.isPress(channel, control, value, status)) {\n+                        if (!this.blockSamplerPad) {\n+                            if (engine.getValue(this.group, 'play') === 1) {\n+                                engine.setValue(this.group, 'play', 0);\n+                            } else {\n+                                engine.setValue(this.group, 'eject', 1);\n+                            }\n+                        }\n+                        this.blockSamplerPad = true;\n+                    } else {\n+                        if (engine.getValue(this.group, 'play') === 0) {\n+                            engine.setValue(this.group, 'eject', 0);\n+                        }\n+                    }\n+                };\n+            },\n+        });\n+\n+        this.hotcueButtons[i] = new components.HotcueButton({\n+            number: i,\n+            midi: [0x90, DJCRMX2.padLedGroups.cue + DJCRMX2.channelGroupsPad[this.currentDeck] + i - 1],\n+        });\n+    }\n+\n+    this.effectUnit = new DJCRMX2.EffectUnit(deckNumbers, false);\n+    this.effectUnit.enableButtons[1].midi = [0x90, DJCRMX2.padLedGroups.effect + DJCRMX2.channelGroupsPad[this.currentDeck] + 0x00];\n+    this.effectUnit.enableButtons[2].midi = [0x90, DJCRMX2.padLedGroups.effect + DJCRMX2.channelGroupsPad[this.currentDeck] + 0x01];\n+    this.effectUnit.enableButtons[3].midi = [0x90, DJCRMX2.padLedGroups.effect + DJCRMX2.channelGroupsPad[this.currentDeck] + 0x02];\n+    this.effectUnit.effectFocusButton.midi = [0x90, DJCRMX2.padLedGroups.effect + DJCRMX2.channelGroupsPad[this.currentDeck] + 0x03];\n+    this.effectUnit.dryWetKnob.input = function(channel, control, value, status, group) {\n+        this.inSetParameter(this.inGetParameter() + DJCRMX2.getRotaryDelta(value) / 40);\n+    };\n+    this.effectUnit.init();\n+\n+    this.loopModeKnob = new components.Encoder({\n+        unshift: function() {\n+            this.inKey = 'beatloop_size';\n+            this.input = function(channel, control, value, status, group) {\n+                if (value === 0x01) {\n+                    this.inSetParameter(this.inGetParameter() * 2);\n+                } else if (value === 0x7F) {\n+                    this.inSetParameter(this.inGetParameter() / 2);\n+                }\n+            };\n+        },\n+        shift: function() {\n+            this.inKey = 'loop_move';\n+            this.input = function(channel, control, value, status, group) {\n+                this.inSetParameter(DJCRMX2.getRotaryDelta(value));\n+            };\n+        },\n+    });\n+\n+    this.samplerModeKnob = new components.Encoder({\n+        number: deckNumbers,\n+        input: function(channel, control, value, status, group) {\n+            // Disconnect samplerButtons:\n+            for (var i = 1; i <= 4; i++) {\n+                if (theDeck.samplerButtons[i] !== undefined) {\n+                    theDeck.samplerButtons[i].disconnect();\n+                    theDeck.samplerButtons[i].send(this.off);\n+                }\n+            }\n+\n+            // Update samplerBankIndex:\n+            if (value === 0x01 && theDeck.samplerBankIndex < 3) {\n+                theDeck.samplerBankIndex = theDeck.samplerBankIndex + 1;\n+            } else if (value === 0x7F && theDeck.samplerBankIndex > 0) {\n+                theDeck.samplerBankIndex = theDeck.samplerBankIndex - 1;\n+            }\n+\n+            // Start flashLEDTimer:\n+            if (DJCRMX2.flashLEDTimer[this.number - 1] !== 0) {\n+                engine.stopTimer(DJCRMX2.flashLEDTimer[this.number - 1]);\n+            }\n+            var callString = \"DJCRMX2.flashLEDHandler('\" + this.group + \"','sampler',\" + theDeck.samplerBankIndex + \")\";\n+            DJCRMX2.flashLEDTimer[this.number - 1] = engine.beginTimer(250, callString);\n+\n+            // Start one-shot samplerBankEditMode stop timer (timeout):\n+            if (this.samplerBankEditModeTimer !== 0) {\n+                engine.stopTimer(this.samplerBankEditModeTimer);\n+            }\n+            this.samplerBankEditModeTimer = engine.beginTimer(3000, this.stopSamplerBankEditMode, true);\n+        },\n+        stopSamplerBankEditMode: function() {\n+            // Stop flashLEDTimer:\n+            if (DJCRMX2.flashLEDTimer[this.number - 1] !== 0) {\n+                engine.stopTimer(DJCRMX2.flashLEDTimer[this.number - 1]);\n+            }\n+\n+            // Reconnect samplerButtons according samplerBankIndex:\n+            for (var i = 1; i <= 4; i++) {\n+                if (theDeck.samplerButtons[i] !== undefined) {\n+                    theDeck.samplerButtons[i].number = i + (4 * theDeck.samplerBankIndex);\n+                    theDeck.samplerButtons[i].group = '[Sampler' + (i + (4 * theDeck.samplerBankIndex)) + ']';\n+                    theDeck.samplerButtons[i].connect();\n+                    theDeck.samplerButtons[i].trigger();\n+                }\n+            }\n+        },\n+    });\n+\n+    this.cueModeKnob = new components.Encoder({\n+        inKey: 'key',\n+        input: function(channel, control, value, status, group) {\n+            if (value === 0x01) {\n+                this.inSetParameter(this.inGetParameter() + 1);\n+            } else if (value === 0x7F) {\n+                this.inSetParameter(this.inGetParameter() - 1);\n+            }\n+        },\n+    });\n+\n+    this.volumeFader = new components.Pot({\n+        inKey: 'volume',\n+    });\n+\n+    this.gainKnob = new components.Pot({\n+        inKey: 'pregain',\n+    });\n+\n+    this.eqKnob = [];\n+    this.eqKillButton = [];\n+    for (var k = 1; k <= 3; k++) {\n+        this.eqKnob[k] = new components.Pot({\n+            deck: this.currentDeck,\n+            number: k,\n+            unshift: function() {\n+                this.group = '[EqualizerRack1_' + this.deck + '_Effect1]';\n+                this.inKey = 'parameter' + this.number;\n+                this.disconnect();\n+                this.connect();\n+            },\n+            shift: function() {\n+                if (this.number === 1) {\n+                    this.group = '[QuickEffectRack1_' + this.deck + ']';\n+                    this.inKey = 'super1';\n+                    this.disconnect();\n+                    this.connect();\n+                }\n+            },\n+        });\n+\n+        this.eqKillButton[k] = new components.Button({\n+            number: k,\n+            midi: [0x90, DJCRMX2.nonPadDeckLeds.killTreble + DJCRMX2.channelGroupsNonPad[this.currentDeck] + 3 - k],\n+            group: '[EqualizerRack1_' + this.currentDeck + '_Effect1]',\n+            key: 'button_parameter' + k,\n+            type: components.Button.prototype.types.toggle,\n+        });\n+    }\n+\n+    this.tempoFader = new components.Pot({\n+        inKey: 'rate',\n+        invert: false,\n+    });\n+\n+    if (!DJCRMX2.vuMeterOutputMaster) {\n+        engine.connectControl(this.currentDeck, 'VuMeter', 'DJCRMX2.vuMeterLeds');\n+    }\n+\n+    this.reconnectComponents(function(c) {\n+        if (c.group === undefined) {\n+            c.group = this.currentDeck;\n+        }\n+    });\n };\n+DJCRMX2.Deck.prototype = new components.Deck();\n \n-DJCRMX2.Deck.prototype.wheelPress = function (value) {\n-    if (this.scratchTimer != 0) {\n+DJCRMX2.Deck.prototype.wheelPress = function(value) {\n+    var deck = this.currentDeck.match(/\\d+/)[0];\n+    if (this.scratchTimer !== 0) {\n         // The wheel was touched again, reset the timer.\n         engine.stopTimer(this.scratchTimer);\n         this.scratchTimer = 0;\n     }\n-    if (value == 0x7F) {\n+    if (value === 0x7F) {\n         // And the jog wheel is pressed down:\n-\n-         /*  engine.scratchEnable(int,int,float,float,float,bool);\n-         * [ int deck ]              Which track/platter is playing?\n-         * [ int intervalsPerRev ]   # of MIDI signals sent in 1 spin.\n-         * [ float rpm ]             Imaginary vinyl rotation speed.\n-         * [ float alpha ]           Just a fine-tuning variable.\n-         * [ float beta ]            Just a fine-tuning variable.\n-         * [ bool ramp ]             As far as I know, nothing...\n-         */\n-\n-         var alpha = 1.0 / 8;\n-         var beta = alpha / 32;\n-         engine.scratchEnable(this.number, 256, 33 + 1/3, alpha, beta);\n+        engine.scratchEnable(deck,\n+            DJCRMX2.scratchSettings.jogResolution,\n+            DJCRMX2.scratchSettings.vinylSpeed,\n+            DJCRMX2.scratchSettings.alpha,\n+            DJCRMX2.scratchSettings.beta);\n     } else {\n         // The wheel touch sensor can be overly sensitive, so don't release scratch mode right away.\n         // Depending on how fast the platter was moving, lengthen the time we'll wait.\n-        var scratchRate = Math.abs(engine.getValue(this.group, \"scratch2\"));\n+        var scratchRate = Math.abs(engine.getValue(this.group, 'scratch2'));\n         var inertiaTime = Math.pow(1.8, scratchRate) * 50;\n         if (inertiaTime < 100) {\n             // Just do it now.\n             this.finishWheelPress();\n-        } else {         \n+        } else {\n             this.scratchTimer = engine.beginTimer(\n-                    100, \"DJCRMX2.decks[\" + this.number + \"].finishWheelPress()\", true);\n+                100, 'DJCRMX2.decks[' + deck + '].finishWheelPress()', true);","path":"res/controllers/Hercules-DJ-Console-RMX-2-scripts.js","position":838,"original_position":838,"commit_id":"1a617e94f51c3597d532af31233d54c0fd41a281","original_commit_id":"1a617e94f51c3597d532af31233d54c0fd41a281","user":{"login":"DJMaxergy","id":26825264,"node_id":"MDQ6VXNlcjI2ODI1MjY0","avatar_url":"https://avatars2.githubusercontent.com/u/26825264?v=4","gravatar_id":"","url":"https://api.github.com/users/DJMaxergy","html_url":"https://github.com/DJMaxergy","followers_url":"https://api.github.com/users/DJMaxergy/followers","following_url":"https://api.github.com/users/DJMaxergy/following{/other_user}","gists_url":"https://api.github.com/users/DJMaxergy/gists{/gist_id}","starred_url":"https://api.github.com/users/DJMaxergy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DJMaxergy/subscriptions","organizations_url":"https://api.github.com/users/DJMaxergy/orgs","repos_url":"https://api.github.com/users/DJMaxergy/repos","events_url":"https://api.github.com/users/DJMaxergy/events{/privacy}","received_events_url":"https://api.github.com/users/DJMaxergy/received_events","type":"User","site_admin":false},"body":"You're right. It was a leftover from the previous mapping. I will change it.","created_at":"2018-09-09T08:04:32Z","updated_at":"2018-09-09T08:04:32Z","html_url":"https://github.com/mixxxdj/mixxx/pull/1718#discussion_r216150587","pull_request_url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/comments/216150587"},"html":{"href":"https://github.com/mixxxdj/mixxx/pull/1718#discussion_r216150587"},"pull_request":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718"}},"in_reply_to_id":207117607},"pull_request":{"url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718","id":196466873,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk2NDY2ODcz","html_url":"https://github.com/mixxxdj/mixxx/pull/1718","diff_url":"https://github.com/mixxxdj/mixxx/pull/1718.diff","patch_url":"https://github.com/mixxxdj/mixxx/pull/1718.patch","issue_url":"https://api.github.com/repos/mixxxdj/mixxx/issues/1718","number":1718,"state":"open","locked":false,"title":"Hercules DJ Console RMX2 mapping overhaul","user":{"login":"DJMaxergy","id":26825264,"node_id":"MDQ6VXNlcjI2ODI1MjY0","avatar_url":"https://avatars2.githubusercontent.com/u/26825264?v=4","gravatar_id":"","url":"https://api.github.com/users/DJMaxergy","html_url":"https://github.com/DJMaxergy","followers_url":"https://api.github.com/users/DJMaxergy/followers","following_url":"https://api.github.com/users/DJMaxergy/following{/other_user}","gists_url":"https://api.github.com/users/DJMaxergy/gists{/gist_id}","starred_url":"https://api.github.com/users/DJMaxergy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DJMaxergy/subscriptions","organizations_url":"https://api.github.com/users/DJMaxergy/orgs","repos_url":"https://api.github.com/users/DJMaxergy/repos","events_url":"https://api.github.com/users/DJMaxergy/events{/privacy}","received_events_url":"https://api.github.com/users/DJMaxergy/received_events","type":"User","site_admin":false},"body":"I did a much more featured mapping for this controller using the components lib. The jog wheel scratch part is the only thing left from the previous mapping (which was nearly all that was written in the old java script file).\r\nI put the focus on the velocity pads and the effects section. I already updated the [wiki](http://www.mixxx.org/wiki/doku.php/hercules_dj_console_rmx_2) for this controller, but I still want to do some additional descriptions using the pads in the different modes.\r\nI tested it now for about one week without any issues.","created_at":"2018-06-21T14:13:51Z","updated_at":"2018-09-09T08:04:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c0f2e03f39b1cdcb80284ef5ccefcbc2e3d36b51","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":518040308,"node_id":"MDU6TGFiZWw1MTgwNDAzMDg=","url":"https://api.github.com/repos/mixxxdj/mixxx/labels/controllers","name":"controllers","color":"009b95","default":false}],"milestone":{"url":"https://api.github.com/repos/mixxxdj/mixxx/milestones/5","html_url":"https://github.com/mixxxdj/mixxx/milestone/5","labels_url":"https://api.github.com/repos/mixxxdj/mixxx/milestones/5/labels","id":3273367,"node_id":"MDk6TWlsZXN0b25lMzI3MzM2Nw==","number":5,"title":"2.1.x","description":"Yet unscheduled changes for the 2.1 release train","creator":{"login":"uklotzde","id":1474154,"node_id":"MDQ6VXNlcjE0NzQxNTQ=","avatar_url":"https://avatars1.githubusercontent.com/u/1474154?v=4","gravatar_id":"","url":"https://api.github.com/users/uklotzde","html_url":"https://github.com/uklotzde","followers_url":"https://api.github.com/users/uklotzde/followers","following_url":"https://api.github.com/users/uklotzde/following{/other_user}","gists_url":"https://api.github.com/users/uklotzde/gists{/gist_id}","starred_url":"https://api.github.com/users/uklotzde/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uklotzde/subscriptions","organizations_url":"https://api.github.com/users/uklotzde/orgs","repos_url":"https://api.github.com/users/uklotzde/repos","events_url":"https://api.github.com/users/uklotzde/events{/privacy}","received_events_url":"https://api.github.com/users/uklotzde/received_events","type":"User","site_admin":false},"open_issues":8,"closed_issues":1,"state":"open","created_at":"2018-04-17T10:22:13Z","updated_at":"2018-07-28T13:45:12Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718/commits","review_comments_url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718/comments","review_comment_url":"https://api.github.com/repos/mixxxdj/mixxx/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mixxxdj/mixxx/issues/1718/comments","statuses_url":"https://api.github.com/repos/mixxxdj/mixxx/statuses/1a617e94f51c3597d532af31233d54c0fd41a281","head":{"label":"DJMaxergy:herculesDJConsoleRMX2mapping_overhaul","ref":"herculesDJConsoleRMX2mapping_overhaul","sha":"1a617e94f51c3597d532af31233d54c0fd41a281","user":{"login":"DJMaxergy","id":26825264,"node_id":"MDQ6VXNlcjI2ODI1MjY0","avatar_url":"https://avatars2.githubusercontent.com/u/26825264?v=4","gravatar_id":"","url":"https://api.github.com/users/DJMaxergy","html_url":"https://github.com/DJMaxergy","followers_url":"https://api.github.com/users/DJMaxergy/followers","following_url":"https://api.github.com/users/DJMaxergy/following{/other_user}","gists_url":"https://api.github.com/users/DJMaxergy/gists{/gist_id}","starred_url":"https://api.github.com/users/DJMaxergy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DJMaxergy/subscriptions","organizations_url":"https://api.github.com/users/DJMaxergy/orgs","repos_url":"https://api.github.com/users/DJMaxergy/repos","events_url":"https://api.github.com/users/DJMaxergy/events{/privacy}","received_events_url":"https://api.github.com/users/DJMaxergy/received_events","type":"User","site_admin":false},"repo":{"id":86984952,"node_id":"MDEwOlJlcG9zaXRvcnk4Njk4NDk1Mg==","name":"mixxx","full_name":"DJMaxergy/mixxx","owner":{"login":"DJMaxergy","id":26825264,"node_id":"MDQ6VXNlcjI2ODI1MjY0","avatar_url":"https://avatars2.githubusercontent.com/u/26825264?v=4","gravatar_id":"","url":"https://api.github.com/users/DJMaxergy","html_url":"https://github.com/DJMaxergy","followers_url":"https://api.github.com/users/DJMaxergy/followers","following_url":"https://api.github.com/users/DJMaxergy/following{/other_user}","gists_url":"https://api.github.com/users/DJMaxergy/gists{/gist_id}","starred_url":"https://api.github.com/users/DJMaxergy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DJMaxergy/subscriptions","organizations_url":"https://api.github.com/users/DJMaxergy/orgs","repos_url":"https://api.github.com/users/DJMaxergy/repos","events_url":"https://api.github.com/users/DJMaxergy/events{/privacy}","received_events_url":"https://api.github.com/users/DJMaxergy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/DJMaxergy/mixxx","description":"Mixxx is Free DJ software that gives you everything you need to perform live mixes.","fork":true,"url":"https://api.github.com/repos/DJMaxergy/mixxx","forks_url":"https://api.github.com/repos/DJMaxergy/mixxx/forks","keys_url":"https://api.github.com/repos/DJMaxergy/mixxx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DJMaxergy/mixxx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DJMaxergy/mixxx/teams","hooks_url":"https://api.github.com/repos/DJMaxergy/mixxx/hooks","issue_events_url":"https://api.github.com/repos/DJMaxergy/mixxx/issues/events{/number}","events_url":"https://api.github.com/repos/DJMaxergy/mixxx/events","assignees_url":"https://api.github.com/repos/DJMaxergy/mixxx/assignees{/user}","branches_url":"https://api.github.com/repos/DJMaxergy/mixxx/branches{/branch}","tags_url":"https://api.github.com/repos/DJMaxergy/mixxx/tags","blobs_url":"https://api.github.com/repos/DJMaxergy/mixxx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DJMaxergy/mixxx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DJMaxergy/mixxx/git/refs{/sha}","trees_url":"https://api.github.com/repos/DJMaxergy/mixxx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DJMaxergy/mixxx/statuses/{sha}","languages_url":"https://api.github.com/repos/DJMaxergy/mixxx/languages","stargazers_url":"https://api.github.com/repos/DJMaxergy/mixxx/stargazers","contributors_url":"https://api.github.com/repos/DJMaxergy/mixxx/contributors","subscribers_url":"https://api.github.com/repos/DJMaxergy/mixxx/subscribers","subscription_url":"https://api.github.com/repos/DJMaxergy/mixxx/subscription","commits_url":"https://api.github.com/repos/DJMaxergy/mixxx/commits{/sha}","git_commits_url":"https://api.github.com/repos/DJMaxergy/mixxx/git/commits{/sha}","comments_url":"https://api.github.com/repos/DJMaxergy/mixxx/comments{/number}","issue_comment_url":"https://api.github.com/repos/DJMaxergy/mixxx/issues/comments{/number}","contents_url":"https://api.github.com/repos/DJMaxergy/mixxx/contents/{+path}","compare_url":"https://api.github.com/repos/DJMaxergy/mixxx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DJMaxergy/mixxx/merges","archive_url":"https://api.github.com/repos/DJMaxergy/mixxx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DJMaxergy/mixxx/downloads","issues_url":"https://api.github.com/repos/DJMaxergy/mixxx/issues{/number}","pulls_url":"https://api.github.com/repos/DJMaxergy/mixxx/pulls{/number}","milestones_url":"https://api.github.com/repos/DJMaxergy/mixxx/milestones{/number}","notifications_url":"https://api.github.com/repos/DJMaxergy/mixxx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DJMaxergy/mixxx/labels{/name}","releases_url":"https://api.github.com/repos/DJMaxergy/mixxx/releases{/id}","deployments_url":"https://api.github.com/repos/DJMaxergy/mixxx/deployments","created_at":"2017-04-02T12:33:31Z","updated_at":"2018-04-21T09:03:20Z","pushed_at":"2018-06-21T08:46:48Z","git_url":"git://github.com/DJMaxergy/mixxx.git","ssh_url":"git@github.com:DJMaxergy/mixxx.git","clone_url":"https://github.com/DJMaxergy/mixxx.git","svn_url":"https://github.com/DJMaxergy/mixxx","homepage":"http://mixxx.org","size":286854,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mixxxdj:2.1","ref":"2.1","sha":"565aceefec82637bb4735fb5aa6b4d18db5e6658","user":{"login":"mixxxdj","id":1743769,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE3NDM3Njk=","avatar_url":"https://avatars3.githubusercontent.com/u/1743769?v=4","gravatar_id":"","url":"https://api.github.com/users/mixxxdj","html_url":"https://github.com/mixxxdj","followers_url":"https://api.github.com/users/mixxxdj/followers","following_url":"https://api.github.com/users/mixxxdj/following{/other_user}","gists_url":"https://api.github.com/users/mixxxdj/gists{/gist_id}","starred_url":"https://api.github.com/users/mixxxdj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mixxxdj/subscriptions","organizations_url":"https://api.github.com/users/mixxxdj/orgs","repos_url":"https://api.github.com/users/mixxxdj/repos","events_url":"https://api.github.com/users/mixxxdj/events{/privacy}","received_events_url":"https://api.github.com/users/mixxxdj/received_events","type":"Organization","site_admin":false},"repo":{"id":10126031,"node_id":"MDEwOlJlcG9zaXRvcnkxMDEyNjAzMQ==","name":"mixxx","full_name":"mixxxdj/mixxx","owner":{"login":"mixxxdj","id":1743769,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE3NDM3Njk=","avatar_url":"https://avatars3.githubusercontent.com/u/1743769?v=4","gravatar_id":"","url":"https://api.github.com/users/mixxxdj","html_url":"https://github.com/mixxxdj","followers_url":"https://api.github.com/users/mixxxdj/followers","following_url":"https://api.github.com/users/mixxxdj/following{/other_user}","gists_url":"https://api.github.com/users/mixxxdj/gists{/gist_id}","starred_url":"https://api.github.com/users/mixxxdj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mixxxdj/subscriptions","organizations_url":"https://api.github.com/users/mixxxdj/orgs","repos_url":"https://api.github.com/users/mixxxdj/repos","events_url":"https://api.github.com/users/mixxxdj/events{/privacy}","received_events_url":"https://api.github.com/users/mixxxdj/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mixxxdj/mixxx","description":"Mixxx is Free DJ software that gives you everything you need to perform live mixes.","fork":false,"url":"https://api.github.com/repos/mixxxdj/mixxx","forks_url":"https://api.github.com/repos/mixxxdj/mixxx/forks","keys_url":"https://api.github.com/repos/mixxxdj/mixxx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mixxxdj/mixxx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mixxxdj/mixxx/teams","hooks_url":"https://api.github.com/repos/mixxxdj/mixxx/hooks","issue_events_url":"https://api.github.com/repos/mixxxdj/mixxx/issues/events{/number}","events_url":"https://api.github.com/repos/mixxxdj/mixxx/events","assignees_url":"https://api.github.com/repos/mixxxdj/mixxx/assignees{/user}","branches_url":"https://api.github.com/repos/mixxxdj/mixxx/branches{/branch}","tags_url":"https://api.github.com/repos/mixxxdj/mixxx/tags","blobs_url":"https://api.github.com/repos/mixxxdj/mixxx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mixxxdj/mixxx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mixxxdj/mixxx/git/refs{/sha}","trees_url":"https://api.github.com/repos/mixxxdj/mixxx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mixxxdj/mixxx/statuses/{sha}","languages_url":"https://api.github.com/repos/mixxxdj/mixxx/languages","stargazers_url":"https://api.github.com/repos/mixxxdj/mixxx/stargazers","contributors_url":"https://api.github.com/repos/mixxxdj/mixxx/contributors","subscribers_url":"https://api.github.com/repos/mixxxdj/mixxx/subscribers","subscription_url":"https://api.github.com/repos/mixxxdj/mixxx/subscription","commits_url":"https://api.github.com/repos/mixxxdj/mixxx/commits{/sha}","git_commits_url":"https://api.github.com/repos/mixxxdj/mixxx/git/commits{/sha}","comments_url":"https://api.github.com/repos/mixxxdj/mixxx/comments{/number}","issue_comment_url":"https://api.github.com/repos/mixxxdj/mixxx/issues/comments{/number}","contents_url":"https://api.github.com/repos/mixxxdj/mixxx/contents/{+path}","compare_url":"https://api.github.com/repos/mixxxdj/mixxx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mixxxdj/mixxx/merges","archive_url":"https://api.github.com/repos/mixxxdj/mixxx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mixxxdj/mixxx/downloads","issues_url":"https://api.github.com/repos/mixxxdj/mixxx/issues{/number}","pulls_url":"https://api.github.com/repos/mixxxdj/mixxx/pulls{/number}","milestones_url":"https://api.github.com/repos/mixxxdj/mixxx/milestones{/number}","notifications_url":"https://api.github.com/repos/mixxxdj/mixxx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mixxxdj/mixxx/labels{/name}","releases_url":"https://api.github.com/repos/mixxxdj/mixxx/releases{/id}","deployments_url":"https://api.github.com/repos/mixxxdj/mixxx/deployments","created_at":"2013-05-17T15:14:38Z","updated_at":"2018-09-07T05:49:26Z","pushed_at":"2018-09-08T00:08:36Z","git_url":"git://github.com/mixxxdj/mixxx.git","ssh_url":"git@github.com:mixxxdj/mixxx.git","clone_url":"https://github.com/mixxxdj/mixxx.git","svn_url":"https://github.com/mixxxdj/mixxx","homepage":"http://mixxx.org","size":293432,"stargazers_count":1098,"watchers_count":1098,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":522,"mirror_url":null,"archived":false,"open_issues_count":88,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":522,"open_issues":88,"watchers":1098,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718"},"html":{"href":"https://github.com/mixxxdj/mixxx/pull/1718"},"issue":{"href":"https://api.github.com/repos/mixxxdj/mixxx/issues/1718"},"comments":{"href":"https://api.github.com/repos/mixxxdj/mixxx/issues/1718/comments"},"review_comments":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718/comments"},"review_comment":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mixxxdj/mixxx/pulls/1718/commits"},"statuses":{"href":"https://api.github.com/repos/mixxxdj/mixxx/statuses/1a617e94f51c3597d532af31233d54c0fd41a281"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"DJMaxergy"}}