From 318025e47ec08af2754a78b6a820f55271aeaf14 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Thu, 14 Nov 2019 16:33:19 +0100 Subject: [PATCH 01/14] src/controllers/colorjsproxy: Add nearestColorMidiCode function --- src/controllers/colorjsproxy.cpp | 45 ++++++++++++++++++++++++++++++++ src/controllers/colorjsproxy.h | 1 + 2 files changed, 46 insertions(+) diff --git a/src/controllers/colorjsproxy.cpp b/src/controllers/colorjsproxy.cpp index f7ef331f704..5b8c5163257 100644 --- a/src/controllers/colorjsproxy.cpp +++ b/src/controllers/colorjsproxy.cpp @@ -1,6 +1,24 @@ +#include +#include #include "controllers/colorjsproxy.h" #include "preferences/hotcuecolorpalettesettings.h" +namespace { + double colorDistance(QColor a, QColor b) + { + long mean_red = ((long)a.red() + (long)b.red()) / 2; + long delta_red = (long)a.red() - (long)b.red(); + long delta_green = (long)a.green() - (long)b.green(); + long delta_blue = (long)a.blue() - (long)b.blue(); + return sqrt( + (((512 + mean_red) * delta_red * delta_red) >> 8) + + (4 * delta_green * delta_green) + + (((767 - mean_red) * delta_blue * delta_blue) >> 8) + ); + } +} + + ColorJSProxy::ColorJSProxy(QScriptEngine* pScriptEngine, HotcueColorPaletteSettings colorPaletteSettings) : m_pScriptEngine(pScriptEngine), @@ -25,6 +43,33 @@ QScriptValue ColorJSProxy::colorFromHexCode(uint colorCode) { return jsColor; } +QScriptValue ColorJSProxy::nearestColorMidiCode(uint colorCode, QVariantMap availableColors) { + QColor desiredColor = QColor::fromRgba(colorCode); + uint nearestColorValue = 0; + double nearestColorDistance = qInf(); + QMapIterator it(availableColors); + while (it.hasNext()) { + it.next(); + QColor availableColor(it.key()); + VERIFY_OR_DEBUG_ASSERT(availableColor.isValid()) { + qWarning() << "Received invalid color name from controller script:" << it.key(); + continue; + } + + double distance = colorDistance(desiredColor, availableColor); + if (distance < nearestColorDistance) { + nearestColorDistance = distance; + bool valueOk; + nearestColorValue = it.value().toUInt(&valueOk); + VERIFY_OR_DEBUG_ASSERT(availableColor.isValid()) { + qWarning() << "Failed to convert value to uint:" << it.value(); + } + qDebug() << "Match for " << desiredColor << " -> " << availableColor << "(distance =" << distance << ", value = " << nearestColorValue << ")"; + } + } + return nearestColorValue; +} + QScriptValue ColorJSProxy::makeHotcueColorPalette(QScriptEngine* pScriptEngine, HotcueColorPaletteSettings colorPaletteSettings) { // TODO: make sure we get notified when the palette changes diff --git a/src/controllers/colorjsproxy.h b/src/controllers/colorjsproxy.h index dda4d693798..45bd52569c8 100644 --- a/src/controllers/colorjsproxy.h +++ b/src/controllers/colorjsproxy.h @@ -21,6 +21,7 @@ class ColorJSProxy final : public QObject { // of a color. The parameter is the hexadecimal representation of the color // i.e. 0xAARRGGBB Q_INVOKABLE QScriptValue colorFromHexCode(uint colorCode); + Q_INVOKABLE QScriptValue nearestColorMidiCode(uint colorCode, QVariantMap availableColorCodes); private: QScriptValue makeHotcueColorPalette(QScriptEngine* pScriptEngine, From 77b3f556b497aa2923a7b1c133a8fcfd6590f677 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Thu, 14 Nov 2019 16:34:02 +0100 Subject: [PATCH 02/14] res/controllers/midi-components: Update HotcueButton to use new API --- res/controllers/midi-components-0.0.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 1893768c2a6..d07220357c9 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -330,20 +330,17 @@ this.send(outval); } }, - outputColor: function (id) { - var color = this.colors[id]; - if (color instanceof Array) { - if (color.length !== 3) { - print("ERROR: invalid color array for id: " + id); - return; - } + outputColor: function (colorCode) { + if (this.colors !== undefined) { + var nearestColor = color.nearestColorMidiCode(colorCode, this.colors); + print("COLOR = "+nearestColor); + this.send(nearestColor); + } else { if (this.sendRGB === undefined) { print("ERROR: no function defined for sending RGB colors"); return; } - this.sendRGB(color); - } else if (typeof color === 'number') { - this.send(color); + this.sendRGB(color.colorFromHexCode(colorCode)); } }, connect: function() { From ad38a407a6d05dbddaa691032033362cba045dd8 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Thu, 14 Nov 2019 16:34:44 +0100 Subject: [PATCH 03/14] Roland DJ-505: Update controller script for new color API --- res/controllers/Roland_DJ-505-scripts.js | 41 ++++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/res/controllers/Roland_DJ-505-scripts.js b/res/controllers/Roland_DJ-505-scripts.js index 2e2777c0e89..428df4bbc81 100644 --- a/res/controllers/Roland_DJ-505-scripts.js +++ b/res/controllers/Roland_DJ-505-scripts.js @@ -941,17 +941,24 @@ DJ505.PadColor = { DIM_MODIFIER: 0x10, }; -DJ505.PadColorMap = [ - DJ505.PadColor.OFF, - DJ505.PadColor.RED, - DJ505.PadColor.GREEN, - DJ505.PadColor.BLUE, - DJ505.PadColor.YELLOW, - DJ505.PadColor.CELESTE, - DJ505.PadColor.PURPLE, - DJ505.PadColor.APRICOT, - DJ505.PadColor.WHITE, -]; +DJ505.PadColorMap = { + '#FFCC0000': DJ505.PadColor.RED, + '#FFCC4400': DJ505.PadColor.CORAL, + '#FFCC8800': DJ505.PadColor.ORANGE, + '#FFCCCC00': DJ505.PadColor.YELLOW, + '#FF88CC00': DJ505.PadColor.GREEN, + '#FF00CC00': DJ505.PadColor.APPLEGREEN, + '#FF00CC88': DJ505.PadColor.AQUAMARINE, + '#FF00CCCC': DJ505.PadColor.TURQUOISE, + '#FF0088CC': DJ505.PadColor.CELESTE, + '#FF0000CC': DJ505.PadColor.BLUE, + '#FF4400CC': DJ505.PadColor.AZURE, + '#FF8800CC': DJ505.PadColor.PURPLE, + '#FFCC00CC': DJ505.PadColor.MAGENTA, + '#FFCC0044': DJ505.PadColor.RED, + '#FFFFCCCC': DJ505.PadColor.APRICOT, + '#FFFFFFFF': DJ505.PadColor.WHITE, +}; DJ505.PadSection = function (deck, offset) { // TODO: Add support for missing modes (flip, slicer, slicerloop) @@ -1190,7 +1197,7 @@ DJ505.HotcueMode = function (deck, offset) { this.ledControl = DJ505.PadMode.HOTCUE; this.color = DJ505.PadColor.WHITE; - var hotcueColors = [this.color].concat(DJ505.PadColorMap.slice(1)); + var hotcueColors = DJ505.PadColorMap; this.pads = new components.ComponentContainer(); for (var i = 0; i <= 7; i++) { this.pads[i] = new components.HotcueButton({ @@ -1226,7 +1233,7 @@ DJ505.CueLoopMode = function (deck, offset) { this.ledControl = DJ505.PadMode.HOTCUE; this.color = DJ505.PadColor.BLUE; - var cueloopColors = [this.color].concat(DJ505.PadColorMap.slice(1)); + var cueloopColors = DJ505.PadColorMap; this.PerformancePad = function(n) { this.midi = [0x94 + offset, 0x14 + n]; this.number = n + 1; @@ -1492,7 +1499,7 @@ DJ505.PitchPlayMode = function (deck, offset) { this.color = DJ505.PadColor.GREEN; this.cuepoint = 1; this.range = PitchPlayRange.MID; - var pitchplayColors = [this.color].concat(DJ505.PadColorMap.slice(1)); + var pitchplayColors = DJ505.PadColorMap; this.PerformancePad = function(n) { this.midi = [0x94 + offset, 0x14 + n]; @@ -1510,10 +1517,10 @@ DJ505.PitchPlayMode = function (deck, offset) { mode: this, outConnect: false, off: DJ505.PadColor.OFF, - outputColor: function(id) { + outputColor: function(colorCode) { // For colored hotcues (shifted only) - var color = this.colors[id]; - this.send((this.mode.cuepoint === this.number) ? color : (color + DJ505.PadColor.DIM_MODIFIER)); + var midiColor = color.nearestColorMidiCode(colorCode, this.colors) + this.send((this.mode.cuepoint === this.number) ? midiColor : (midiColor + DJ505.PadColor.DIM_MODIFIER)); }, unshift: function() { this.outKey = "pitch_adjust"; From b873ca2fe0793f93c83884c5a59b31161957583d Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Fri, 15 Nov 2019 23:05:58 +0100 Subject: [PATCH 04/14] src/controllers/colorjsproxy: Fix indentation in colorDistance function --- src/controllers/colorjsproxy.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/controllers/colorjsproxy.cpp b/src/controllers/colorjsproxy.cpp index 5b8c5163257..15620cc23b3 100644 --- a/src/controllers/colorjsproxy.cpp +++ b/src/controllers/colorjsproxy.cpp @@ -6,15 +6,15 @@ namespace { double colorDistance(QColor a, QColor b) { - long mean_red = ((long)a.red() + (long)b.red()) / 2; - long delta_red = (long)a.red() - (long)b.red(); - long delta_green = (long)a.green() - (long)b.green(); - long delta_blue = (long)a.blue() - (long)b.blue(); - return sqrt( - (((512 + mean_red) * delta_red * delta_red) >> 8) + - (4 * delta_green * delta_green) + - (((767 - mean_red) * delta_blue * delta_blue) >> 8) - ); + long mean_red = ((long)a.red() + (long)b.red()) / 2; + long delta_red = (long)a.red() - (long)b.red(); + long delta_green = (long)a.green() - (long)b.green(); + long delta_blue = (long)a.blue() - (long)b.blue(); + return sqrt( + (((512 + mean_red) * delta_red * delta_red) >> 8) + + (4 * delta_green * delta_green) + + (((767 - mean_red) * delta_blue * delta_blue) >> 8) + ); } } From 1d058583b5cab267e651ef095848697a07c23827 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Fri, 15 Nov 2019 23:19:57 +0100 Subject: [PATCH 05/14] src/controllers/colorjsproxy: Add comment to colorDistance algorithm --- src/controllers/colorjsproxy.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/controllers/colorjsproxy.cpp b/src/controllers/colorjsproxy.cpp index 15620cc23b3..c86dd4f4b66 100644 --- a/src/controllers/colorjsproxy.cpp +++ b/src/controllers/colorjsproxy.cpp @@ -6,6 +6,13 @@ namespace { double colorDistance(QColor a, QColor b) { + // This algorithm calculates the distance between two colors. In + // contrast to the L2 norm, this also tries take the human perception + // of colors into account. More accurate algorithms like the CIELAB2000 + // Delta-E rely on sophisticated color space conversions and need a lot + // of costly computations. In contrast, this is a low-cost + // approximation and should be sufficently accurate. + // More details: https://www.compuphase.com/cmetric.htm long mean_red = ((long)a.red() + (long)b.red()) / 2; long delta_red = (long)a.red() - (long)b.red(); long delta_green = (long)a.green() - (long)b.green(); From 2b61025cded6054375928cc3695b80dd115aecc5 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Sat, 16 Nov 2019 04:18:36 +0100 Subject: [PATCH 06/14] src/controllers: Add ColorMapper class for controller scripts --- build/depends.py | 2 + src/controllers/colorjsproxy.cpp | 52 ----------------------- src/controllers/colorjsproxy.h | 1 - src/controllers/colormapper.cpp | 59 ++++++++++++++++++++++++++ src/controllers/colormapper.h | 30 +++++++++++++ src/controllers/colormapperjsproxy.cpp | 37 ++++++++++++++++ src/controllers/colormapperjsproxy.h | 29 +++++++++++++ src/controllers/controllerengine.cpp | 6 ++- 8 files changed, 162 insertions(+), 54 deletions(-) create mode 100644 src/controllers/colormapper.cpp create mode 100644 src/controllers/colormapper.h create mode 100644 src/controllers/colormapperjsproxy.cpp create mode 100644 src/controllers/colormapperjsproxy.h diff --git a/build/depends.py b/build/depends.py index 202419e6199..ac5e778feee 100644 --- a/build/depends.py +++ b/build/depends.py @@ -913,6 +913,8 @@ def sources(self, build): "src/controllers/softtakeover.cpp", "src/controllers/keyboard/keyboardeventfilter.cpp", "src/controllers/colorjsproxy.cpp", + "src/controllers/colormapper.cpp", + "src/controllers/colormapperjsproxy.cpp", "src/main.cpp", "src/mixxx.cpp", diff --git a/src/controllers/colorjsproxy.cpp b/src/controllers/colorjsproxy.cpp index c86dd4f4b66..f7ef331f704 100644 --- a/src/controllers/colorjsproxy.cpp +++ b/src/controllers/colorjsproxy.cpp @@ -1,31 +1,6 @@ -#include -#include #include "controllers/colorjsproxy.h" #include "preferences/hotcuecolorpalettesettings.h" -namespace { - double colorDistance(QColor a, QColor b) - { - // This algorithm calculates the distance between two colors. In - // contrast to the L2 norm, this also tries take the human perception - // of colors into account. More accurate algorithms like the CIELAB2000 - // Delta-E rely on sophisticated color space conversions and need a lot - // of costly computations. In contrast, this is a low-cost - // approximation and should be sufficently accurate. - // More details: https://www.compuphase.com/cmetric.htm - long mean_red = ((long)a.red() + (long)b.red()) / 2; - long delta_red = (long)a.red() - (long)b.red(); - long delta_green = (long)a.green() - (long)b.green(); - long delta_blue = (long)a.blue() - (long)b.blue(); - return sqrt( - (((512 + mean_red) * delta_red * delta_red) >> 8) + - (4 * delta_green * delta_green) + - (((767 - mean_red) * delta_blue * delta_blue) >> 8) - ); - } -} - - ColorJSProxy::ColorJSProxy(QScriptEngine* pScriptEngine, HotcueColorPaletteSettings colorPaletteSettings) : m_pScriptEngine(pScriptEngine), @@ -50,33 +25,6 @@ QScriptValue ColorJSProxy::colorFromHexCode(uint colorCode) { return jsColor; } -QScriptValue ColorJSProxy::nearestColorMidiCode(uint colorCode, QVariantMap availableColors) { - QColor desiredColor = QColor::fromRgba(colorCode); - uint nearestColorValue = 0; - double nearestColorDistance = qInf(); - QMapIterator it(availableColors); - while (it.hasNext()) { - it.next(); - QColor availableColor(it.key()); - VERIFY_OR_DEBUG_ASSERT(availableColor.isValid()) { - qWarning() << "Received invalid color name from controller script:" << it.key(); - continue; - } - - double distance = colorDistance(desiredColor, availableColor); - if (distance < nearestColorDistance) { - nearestColorDistance = distance; - bool valueOk; - nearestColorValue = it.value().toUInt(&valueOk); - VERIFY_OR_DEBUG_ASSERT(availableColor.isValid()) { - qWarning() << "Failed to convert value to uint:" << it.value(); - } - qDebug() << "Match for " << desiredColor << " -> " << availableColor << "(distance =" << distance << ", value = " << nearestColorValue << ")"; - } - } - return nearestColorValue; -} - QScriptValue ColorJSProxy::makeHotcueColorPalette(QScriptEngine* pScriptEngine, HotcueColorPaletteSettings colorPaletteSettings) { // TODO: make sure we get notified when the palette changes diff --git a/src/controllers/colorjsproxy.h b/src/controllers/colorjsproxy.h index 45bd52569c8..dda4d693798 100644 --- a/src/controllers/colorjsproxy.h +++ b/src/controllers/colorjsproxy.h @@ -21,7 +21,6 @@ class ColorJSProxy final : public QObject { // of a color. The parameter is the hexadecimal representation of the color // i.e. 0xAARRGGBB Q_INVOKABLE QScriptValue colorFromHexCode(uint colorCode); - Q_INVOKABLE QScriptValue nearestColorMidiCode(uint colorCode, QVariantMap availableColorCodes); private: QScriptValue makeHotcueColorPalette(QScriptEngine* pScriptEngine, diff --git a/src/controllers/colormapper.cpp b/src/controllers/colormapper.cpp new file mode 100644 index 00000000000..3caa515806e --- /dev/null +++ b/src/controllers/colormapper.cpp @@ -0,0 +1,59 @@ +#include "controllers/colormapper.h" + +#include +#include + +#include "util/debug.h" + +namespace { +double colorDistance(QRgb a, QRgb b) { + // This algorithm calculates the distance between two colors. In + // contrast to the L2 norm, this also tries take the human perception + // of colors into account. More accurate algorithms like the CIELAB2000 + // Delta-E rely on sophisticated color space conversions and need a lot + // of costly computations. In contrast, this is a low-cost + // approximation and should be sufficently accurate. + // More details: https://www.compuphase.com/cmetric.htm + long mean_red = ((long)qRed(a) + (long)qRed(b)) / 2; + long delta_red = (long)qRed(a) - (long)qRed(b); + long delta_green = (long)qGreen(a) - (long)qGreen(b); + long delta_blue = (long)qBlue(a) - (long)qBlue(b); + return sqrt( + (((512 + mean_red) * delta_red * delta_red) >> 8) + + (4 * delta_green * delta_green) + + (((767 - mean_red) * delta_blue * delta_blue) >> 8)); +} +} // namespace + +QPair ColorMapper::getNearestColor(QRgb desiredColor) { + // If desired color is already in cache, use cache entry + QMap::const_iterator i = m_cache.find(desiredColor); + QMap::const_iterator j; + if (i != m_cache.constEnd()) { + j = m_availableColors.find(i.value()); + DEBUG_ASSERT(j != m_availableColors.constEnd()); + qDebug() << "ColorMapper cache hit for" << desiredColor << ":" + << "Color =" << j.key() << "," + << "Value =" << j.value(); + return QPair(j.key(), j.value()); + } + + // Color is not cached + QMap::const_iterator nearestColorIterator; + double nearestColorDistance = qInf(); + for (j = m_availableColors.constBegin(); j != m_availableColors.constEnd(); j++) { + QRgb availableColor = j.key(); + double distance = colorDistance(desiredColor, availableColor); + if (distance < nearestColorDistance) { + nearestColorDistance = distance; + nearestColorIterator = j; + } + } + + DEBUG_ASSERT(nearestColorDistance < qInf()); + qDebug() << "ColorMapper found matching color for" << desiredColor << ":" + << "Color =" << nearestColorIterator.key() << "," + << "Value =" << nearestColorIterator.value(); + m_cache.insert(desiredColor, nearestColorIterator.key()); + return QPair(nearestColorIterator.key(), nearestColorIterator.value()); +} diff --git a/src/controllers/colormapper.h b/src/controllers/colormapper.h new file mode 100644 index 00000000000..c138edbf38d --- /dev/null +++ b/src/controllers/colormapper.h @@ -0,0 +1,30 @@ +#ifndef COLORMAPPER_H +#define COLORMAPPER_H + +#include +#include +#include +#include +#include + +#include "util/assert.h" + +class ColorMapper final : public QObject { + Q_OBJECT + public: + ColorMapper() = delete; + ColorMapper(const QMap availableColors) + : m_availableColors(availableColors) { + DEBUG_ASSERT(!m_availableColors.isEmpty()); + } + + ~ColorMapper() = default; + + QPair getNearestColor(QRgb desiredColor); + + private: + const QMap m_availableColors; + QMap m_cache; +}; + +#endif /* COLORMAPPER_H */ diff --git a/src/controllers/colormapperjsproxy.cpp b/src/controllers/colormapperjsproxy.cpp new file mode 100644 index 00000000000..3e1db371780 --- /dev/null +++ b/src/controllers/colormapperjsproxy.cpp @@ -0,0 +1,37 @@ +#include + +#include "controllers/colormapperjsproxy.h" + +ColorMapperJSProxy::ColorMapperJSProxy(QScriptEngine* pScriptEngine, QMap availableColors) + : m_pScriptEngine(pScriptEngine) { + m_colorMapper = new ColorMapper(availableColors); +} + +QScriptValue ColorMapperJSProxy::getNearestColor(uint colorCode) { + QPair result = m_colorMapper->getNearestColor(static_cast(colorCode)); + return m_pScriptEngine->toScriptValue(result.second); +} + +QScriptValue ColorMapperJSProxyConstructor(QScriptContext* pScriptContext, QScriptEngine* pScriptEngine) { + QMap availableColors; + DEBUG_ASSERT(pScriptContext->argumentCount() == 1); + QScriptValueIterator it(pScriptContext->argument(0)); + while (it.hasNext()) { + it.next(); + DEBUG_ASSERT(!it.value().isObject()); + QColor color(it.name()); + VERIFY_OR_DEBUG_ASSERT(color.isValid()) { + qWarning() << "Received invalid color name from controller script:" << it.name(); + continue; + } + availableColors.insert(color.rgb(), it.value().toVariant()); + } + + if (availableColors.isEmpty()) { + qWarning() << "Failed to create ColorMapper object: available colors mustn't be empty!"; + return pScriptEngine->undefinedValue(); + } + + QObject* colorMapper = new ColorMapperJSProxy(pScriptEngine, availableColors); + return pScriptEngine->newQObject(colorMapper, QScriptEngine::ScriptOwnership); +} diff --git a/src/controllers/colormapperjsproxy.h b/src/controllers/colormapperjsproxy.h new file mode 100644 index 00000000000..eb5643e27bf --- /dev/null +++ b/src/controllers/colormapperjsproxy.h @@ -0,0 +1,29 @@ +#ifndef COLORMAPPERJS_H +#define COLORMAPPERJS_H + +#include +#include + +#include "controllers/colormapper.h" + +class ColorMapperJSProxy final : public QObject { + Q_OBJECT + public: + ColorMapperJSProxy() = delete; + ColorMapperJSProxy(QScriptEngine* pScriptEngine, QMap availableColors); + + ~ColorMapperJSProxy() { + delete m_colorMapper; + }; + + public slots: + QScriptValue getNearestColor(uint ColorCode); + + private: + QScriptEngine* m_pScriptEngine; + ColorMapper* m_colorMapper; +}; + +QScriptValue ColorMapperJSProxyConstructor(QScriptContext* context, QScriptEngine* engine); + +#endif /* COLORMAPPER_H */ diff --git a/src/controllers/controllerengine.cpp b/src/controllers/controllerengine.cpp index 9bee7c4209e..e01e8943a1c 100644 --- a/src/controllers/controllerengine.cpp +++ b/src/controllers/controllerengine.cpp @@ -6,8 +6,8 @@ email : spappalardo@mixxx.org ***************************************************************************/ +#include "controllers/colormapperjsproxy.h" #include "controllers/controllerengine.h" - #include "controllers/controller.h" #include "controllers/controllerdebug.h" #include "control/controlobject.h" @@ -219,6 +219,10 @@ void ControllerEngine::initializeScriptEngine() { m_pEngine, HotcueColorPaletteSettings(m_pConfig)); engineGlobalObject.setProperty("color", m_pEngine->newQObject(m_pColorJSProxy.get())); + QScriptValue constructor = m_pEngine->newFunction(ColorMapperJSProxyConstructor); + QScriptValue metaObject = m_pEngine->newQMetaObject(&ColorMapperJSProxy::staticMetaObject, constructor); + engineGlobalObject.setProperty("ColorMapper", metaObject); + m_pBaClass = new ByteArrayClass(m_pEngine); engineGlobalObject.setProperty("ByteArray", m_pBaClass->constructor()); } From a24b22a91daaebcaa74cedd87154c550562f2667 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Sat, 16 Nov 2019 04:19:45 +0100 Subject: [PATCH 07/14] res/controllers/midi-components: Add support for ColorMapper class --- res/controllers/midi-components-0.0.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index d07220357c9..2d3d0f1943a 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -332,7 +332,7 @@ }, outputColor: function (colorCode) { if (this.colors !== undefined) { - var nearestColor = color.nearestColorMidiCode(colorCode, this.colors); + var nearestColor = this.colors.getNearestColor(colorCode); print("COLOR = "+nearestColor); this.send(nearestColor); } else { From 3f42532ed8b7148d679f09d419906dc97a8d7ab6 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Sat, 16 Nov 2019 04:20:28 +0100 Subject: [PATCH 08/14] Roland DJ-505: Add support for ColorMapper class --- res/controllers/Roland_DJ-505-scripts.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/controllers/Roland_DJ-505-scripts.js b/res/controllers/Roland_DJ-505-scripts.js index 428df4bbc81..6e010d76701 100644 --- a/res/controllers/Roland_DJ-505-scripts.js +++ b/res/controllers/Roland_DJ-505-scripts.js @@ -941,7 +941,7 @@ DJ505.PadColor = { DIM_MODIFIER: 0x10, }; -DJ505.PadColorMap = { +DJ505.PadColorMap = new ColorMapper({ '#FFCC0000': DJ505.PadColor.RED, '#FFCC4400': DJ505.PadColor.CORAL, '#FFCC8800': DJ505.PadColor.ORANGE, @@ -958,7 +958,7 @@ DJ505.PadColorMap = { '#FFCC0044': DJ505.PadColor.RED, '#FFFFCCCC': DJ505.PadColor.APRICOT, '#FFFFFFFF': DJ505.PadColor.WHITE, -}; +}); DJ505.PadSection = function (deck, offset) { // TODO: Add support for missing modes (flip, slicer, slicerloop) @@ -1519,7 +1519,7 @@ DJ505.PitchPlayMode = function (deck, offset) { off: DJ505.PadColor.OFF, outputColor: function(colorCode) { // For colored hotcues (shifted only) - var midiColor = color.nearestColorMidiCode(colorCode, this.colors) + var midiColor = this.colors.getNearestColor(colorCode); this.send((this.mode.cuepoint === this.number) ? midiColor : (midiColor + DJ505.PadColor.DIM_MODIFIER)); }, unshift: function() { From efde9e45ad7906a4e6915cb5053633e1d8fd967f Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 18:48:40 +0100 Subject: [PATCH 09/14] controllers/colormapperjsproxy: Add separate getNearestValue method --- res/controllers/midi-components-0.0.js | 6 +++--- src/controllers/colormapperjsproxy.cpp | 10 ++++++++++ src/controllers/colormapperjsproxy.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 2d3d0f1943a..1af0bf8454a 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -332,9 +332,9 @@ }, outputColor: function (colorCode) { if (this.colors !== undefined) { - var nearestColor = this.colors.getNearestColor(colorCode); - print("COLOR = "+nearestColor); - this.send(nearestColor); + var nearestColorValue = this.colors.getNearestValue(colorCode); + print("COLOR = "+nearestColorValue); + this.send(nearestColorValue); } else { if (this.sendRGB === undefined) { print("ERROR: no function defined for sending RGB colors"); diff --git a/src/controllers/colormapperjsproxy.cpp b/src/controllers/colormapperjsproxy.cpp index 3e1db371780..f806cb9752e 100644 --- a/src/controllers/colormapperjsproxy.cpp +++ b/src/controllers/colormapperjsproxy.cpp @@ -8,6 +8,16 @@ ColorMapperJSProxy::ColorMapperJSProxy(QScriptEngine* pScriptEngine, QMap result = m_colorMapper->getNearestColor(static_cast(colorCode)); + QScriptValue jsColor = m_pScriptEngine->newObject(); + jsColor.setProperty("red", qRed(result.first)); + jsColor.setProperty("green", qGreen(result.first)); + jsColor.setProperty("blue", qBlue(result.first)); + jsColor.setProperty("alpha", qAlpha(result.first)); + return jsColor; +} + +QScriptValue ColorMapperJSProxy::getNearestValue(uint colorCode) { QPair result = m_colorMapper->getNearestColor(static_cast(colorCode)); return m_pScriptEngine->toScriptValue(result.second); } diff --git a/src/controllers/colormapperjsproxy.h b/src/controllers/colormapperjsproxy.h index eb5643e27bf..367d13bba3e 100644 --- a/src/controllers/colormapperjsproxy.h +++ b/src/controllers/colormapperjsproxy.h @@ -18,6 +18,7 @@ class ColorMapperJSProxy final : public QObject { public slots: QScriptValue getNearestColor(uint ColorCode); + QScriptValue getNearestValue(uint ColorCode); private: QScriptEngine* m_pScriptEngine; From b94a72f7d52865078e8ac5be42e1158a2c2da89d Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 18:49:12 +0100 Subject: [PATCH 10/14] Roland DJ-505: Switch to ControllerMapper::getNearestValue --- res/controllers/Roland_DJ-505-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Roland_DJ-505-scripts.js b/res/controllers/Roland_DJ-505-scripts.js index 6e010d76701..659b5cb54fc 100644 --- a/res/controllers/Roland_DJ-505-scripts.js +++ b/res/controllers/Roland_DJ-505-scripts.js @@ -1519,7 +1519,7 @@ DJ505.PitchPlayMode = function (deck, offset) { off: DJ505.PadColor.OFF, outputColor: function(colorCode) { // For colored hotcues (shifted only) - var midiColor = this.colors.getNearestColor(colorCode); + var midiColor = this.colors.getNearestValue(colorCode); this.send((this.mode.cuepoint === this.number) ? midiColor : (midiColor + DJ505.PadColor.DIM_MODIFIER)); }, unshift: function() { From 6c0e9699a78ad9206d73850c9f0f9a90bf57d368 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 18:54:41 +0100 Subject: [PATCH 11/14] controllers/midi-components: Remove default value for HotcueButton.colors --- res/controllers/midi-components-0.0.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 1af0bf8454a..79a577d88dc 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -296,9 +296,6 @@ } if (options.colors !== undefined || options.sendRGB !== undefined) { this.colorKey = 'hotcue_' + options.number + '_color'; - if (options.colors === undefined) { - options.colors = color.hotcueColorPalette(); - } } this.number = options.number; this.outKey = 'hotcue_' + this.number + '_enabled'; From 91f178b36a60bc5b2f3cdfed3ff0bb923507e242 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 18:55:23 +0100 Subject: [PATCH 12/14] controllers/midi-components: Rename HotcueButton.colors to .colorMapper --- res/controllers/midi-components-0.0.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 79a577d88dc..c4685e75ea5 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -294,7 +294,7 @@ print('ERROR: No hotcue number specified for new HotcueButton.'); return; } - if (options.colors !== undefined || options.sendRGB !== undefined) { + if (options.colorMapper !== undefined || options.sendRGB !== undefined) { this.colorKey = 'hotcue_' + options.number + '_color'; } this.number = options.number; @@ -328,8 +328,8 @@ } }, outputColor: function (colorCode) { - if (this.colors !== undefined) { - var nearestColorValue = this.colors.getNearestValue(colorCode); + if (this.colorMapper !== undefined) { + var nearestColorValue = this.colorMapper.getNearestValue(colorCode); print("COLOR = "+nearestColorValue); this.send(nearestColorValue); } else { From 4bb6d64719d0f0211b523288d4b3244159144529 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 18:59:18 +0100 Subject: [PATCH 13/14] Roland DJ-505: Rename Component.colors to .colorMapper --- res/controllers/Roland_DJ-505-scripts.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/res/controllers/Roland_DJ-505-scripts.js b/res/controllers/Roland_DJ-505-scripts.js index 659b5cb54fc..25efbbfb523 100644 --- a/res/controllers/Roland_DJ-505-scripts.js +++ b/res/controllers/Roland_DJ-505-scripts.js @@ -1197,7 +1197,6 @@ DJ505.HotcueMode = function (deck, offset) { this.ledControl = DJ505.PadMode.HOTCUE; this.color = DJ505.PadColor.WHITE; - var hotcueColors = DJ505.PadColorMap; this.pads = new components.ComponentContainer(); for (var i = 0; i <= 7; i++) { this.pads[i] = new components.HotcueButton({ @@ -1209,7 +1208,7 @@ DJ505.HotcueMode = function (deck, offset) { group: deck.currentDeck, on: this.color, off: this.color + DJ505.PadColor.DIM_MODIFIER, - colors: hotcueColors, + colorMapper: DJ505.PadColorMap, outConnect: false, }); } @@ -1233,7 +1232,6 @@ DJ505.CueLoopMode = function (deck, offset) { this.ledControl = DJ505.PadMode.HOTCUE; this.color = DJ505.PadColor.BLUE; - var cueloopColors = DJ505.PadColorMap; this.PerformancePad = function(n) { this.midi = [0x94 + offset, 0x14 + n]; this.number = n + 1; @@ -1248,7 +1246,7 @@ DJ505.CueLoopMode = function (deck, offset) { group: deck.currentDeck, on: this.color, off: this.color + DJ505.PadColor.DIM_MODIFIER, - colors: cueloopColors, + colorMapper: DJ505.PadColorMap, outConnect: false, unshift: function() { this.input = function (channel, control, value, status, group) { @@ -1499,13 +1497,12 @@ DJ505.PitchPlayMode = function (deck, offset) { this.color = DJ505.PadColor.GREEN; this.cuepoint = 1; this.range = PitchPlayRange.MID; - var pitchplayColors = DJ505.PadColorMap; this.PerformancePad = function(n) { this.midi = [0x94 + offset, 0x14 + n]; this.number = n + 1; this.on = this.color + DJ505.PadColor.DIM_MODIFIER; - this.colors = pitchplayColors; + this.colorMapper = DJ505.PadColorMap; this.colorKey = 'hotcue_' + this.number + '_color'; components.Button.call(this); }; @@ -1519,7 +1516,7 @@ DJ505.PitchPlayMode = function (deck, offset) { off: DJ505.PadColor.OFF, outputColor: function(colorCode) { // For colored hotcues (shifted only) - var midiColor = this.colors.getNearestValue(colorCode); + var midiColor = this.colorMapper.getNearestValue(colorCode); this.send((this.mode.cuepoint === this.number) ? midiColor : (midiColor + DJ505.PadColor.DIM_MODIFIER)); }, unshift: function() { From 4ea1ac53a6b94c2984d2e3296e5185a049a63b56 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 19 Nov 2019 19:04:59 +0100 Subject: [PATCH 14/14] controllers/midi-components: Remove old print statement --- res/controllers/midi-components-0.0.js | 1 - 1 file changed, 1 deletion(-) diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index c4685e75ea5..9c07c14b723 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -330,7 +330,6 @@ outputColor: function (colorCode) { if (this.colorMapper !== undefined) { var nearestColorValue = this.colorMapper.getNearestValue(colorCode); - print("COLOR = "+nearestColorValue); this.send(nearestColorValue); } else { if (this.sendRGB === undefined) {