From 826b964bf6aefc87751a22c4218109898087a8d8 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 10:48:10 +0000 Subject: [PATCH] Implemented the multi-color transform including in hyperion-remote Former-commit-id: ebdb0688b47d51bd6dccf6dafd580d3ce9ed80a7 --- config/hyperion.config.json | 82 +++---- include/hyperion/ColorTransform.h | 26 +++ include/hyperion/Hyperion.h | 31 +-- libsrc/hyperion/CMakeLists.txt | 1 + libsrc/hyperion/Hyperion.cpp | 209 ++++++++---------- libsrc/hyperion/MultiColorTransform.cpp | 48 ++-- libsrc/hyperion/MultiColorTransform.h | 37 ++-- libsrc/jsonserver/JsonClientConnection.cpp | 103 +++++---- .../jsonserver/schema/schema-transform.json | 136 ++++++------ src/hyperion-remote/JsonConnection.cpp | 7 +- src/hyperion-remote/JsonConnection.h | 2 + src/hyperion-remote/hyperion-remote.cpp | 5 + 12 files changed, 357 insertions(+), 330 deletions(-) create mode 100644 include/hyperion/ColorTransform.h diff --git a/config/hyperion.config.json b/config/hyperion.config.json index bba5ce09..fa6a7535 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -2,7 +2,7 @@ // Generated by: HyperCon (The Hyperion deamon configuration file builder { - /// Device configuration contains the following fields: + /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none') @@ -34,32 +34,38 @@ /// - 'updateFrequency' The update frequency of the leds in Hz "color" : { - "hsv" : - { - "saturationGain" : 1.0000, - "valueGain" : 1.5000 - }, - "red" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 0.8000 - }, - "green" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, - "blue" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, + "transforms" : + [ + { + "id" : "default", + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 + }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + } + ], "smoothing" : { "type" : "none", @@ -68,16 +74,16 @@ } }, - /// The configuration for each individual led. This contains the specification of the area - /// averaged of an input image for each led to determine its color. Each item in the list + /// The configuration for each individual led. This contains the specification of the area + /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: - /// * index: The index of the led. This determines its location in the string of leds; zero + /// * index: The index of the led. This determines its location in the string of leds; zero /// being the first led. - /// * hscan: The fractional part of the image along the horizontal used for the averaging + /// * hscan: The fractional part of the image along the horizontal used for the averaging /// (minimum and maximum inclusive) - /// * vscan: The fractional part of the image along the vertical used for the averaging + /// * vscan: The fractional part of the image along the vertical used for the averaging /// (minimum and maximum inclusive) - "leds" : + "leds" : [ { "index" : 0, @@ -331,15 +337,15 @@ } ], - /// The black border configuration, contains the following items: + /// The black border configuration, contains the following items: /// * enable : true if the detector should be activated "blackborderdetector" : { "enable" : true }, - /// The boot-sequence configuration, contains the following items: - /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') + /// The boot-sequence configuration, contains the following items: + /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') /// * duration_ms : The length of the boot-sequence [ms] "bootsequence" : { @@ -347,7 +353,7 @@ "duration_ms" : 3000 }, - /// The configuration for the frame-grabber, contains the following items: + /// The configuration for the frame-grabber, contains the following items: /// * width : The width of the grabbed frames [pixels] /// * height : The height of the grabbed frames [pixels] /// * frequency_Hz : The frequency of the frame grab [Hz] @@ -358,7 +364,7 @@ "frequency_Hz" : 10.0 }, - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: + /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: /// * xbmcAddress : The IP address of the XBMC-host /// * xbmcTcpPort : The TCP-port of the XBMC-server /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback diff --git a/include/hyperion/ColorTransform.h b/include/hyperion/ColorTransform.h new file mode 100644 index 00000000..50cbedba --- /dev/null +++ b/include/hyperion/ColorTransform.h @@ -0,0 +1,26 @@ +#pragma once + +// STL includes +#include + +// Utils includes +#include +#include + +class ColorTransform +{ +public: + + /// Unique identifier for this color transform + std::string _id; + + /// The RED-Channel (RGB) transform + RgbChannelTransform _rgbRedTransform; + /// The GREEN-Channel (RGB) transform + RgbChannelTransform _rgbGreenTransform; + /// The BLUE-Channel (RGB) transform + RgbChannelTransform _rgbBlueTransform; + + /// The HSV Transform for applying Saturation and Value transforms + HsvTransform _hsvTransform; +}; diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 6f726241..605ce6a1 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -16,6 +16,7 @@ #include // Forward class declaration +class ColorTransform; class HsvTransform; class RgbChannelTransform; class MultiColorTransform; @@ -89,15 +90,16 @@ public: void setColors(int priority, const std::vector &ledColors, const int timeout_ms); /// - /// Sets/Updates a part of the color transformation. + /// Returns the list with unique transform identifiers + /// @return The list with transform identifiers /// - /// @param[in] transform The type of transform to configure - /// @param[in] color The color channel to which the transform applies (only applicable for - /// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL, - /// Transform::WHITELEVEL) - /// @param[in] value The new value for the given transform + const std::vector & getTransformIds() const; + /// - void setTransform(Transform transform, RgbChannel color, double value); + /// Returns the ColorTransform with the given identifier + /// @return The transform with the given identifier (or nullptr if the identifier does not exist) + /// + ColorTransform * getTransform(const std::string& id); /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next @@ -112,18 +114,6 @@ public: /// void clearall(); - /// - /// Returns the value of a specific color transform - /// - /// @param[in] transform The type of transform - /// @param[in] color The color channel to which the transform applies (only applicable for - /// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL, - /// Transform::WHITELEVEL) - /// - /// @return The value of the specified color transform - /// - double getTransform(Transform transform, RgbChannel color) const; - /// /// Returns a list of active priorities /// @@ -147,8 +137,9 @@ public: static LedString createLedString(const Json::Value & ledsConfig); static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig); + static ColorTransform * createColorTransform(const Json::Value & transformConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); - static RgbChannelTransform * createColorTransform(const Json::Value& colorConfig); + static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 03d9df24..c984aa62 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -77,6 +77,7 @@ add_library(hyperion ${Hyperion_SOURCES} ${Hyperion_RESOURCES_RCC} ) +message("{QT_LIBRARIES} = ${QT_LIBRARIES}") target_link_libraries(hyperion hyperion-utils diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 64b1be63..472ae96f 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -4,6 +4,9 @@ // QT includes #include +#include +#include +#include // JsonSchema include #include @@ -153,29 +156,94 @@ Hyperion::ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig) return ORDER_RGB; } +ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig) +{ + const std::string id = transformConfig.get("id", "default").asString(); + + RgbChannelTransform * redTransform = createRgbChannelTransform(transformConfig["red"]); + RgbChannelTransform * greenTransform = createRgbChannelTransform(transformConfig["green"]); + RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"]); + + HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"]); + + ColorTransform * transform = new ColorTransform(); + transform->_id = id; + transform->_rgbRedTransform = *redTransform; + transform->_rgbGreenTransform = *greenTransform; + transform->_rgbBlueTransform = *blueTransform; + transform->_hsvTransform = *hsvTransform; + + // Cleanup the allocated individual transforms + delete redTransform; + delete greenTransform; + delete blueTransform; + delete hsvTransform; + + return transform; +} + MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig) { - MultiColorTransform * transform = new MultiColorTransform(); - if (!colorConfig.isArray()) + // Create the result, the transforms are added to this + MultiColorTransform * transform = new MultiColorTransform(ledCnt); + + const Json::Value transformConfig = colorConfig.get("transform", Json::nullValue); + if (transformConfig.isNull()) { // Old style color transformation config (just one for all leds) - const std::string id = "default"; - - RgbChannelTransform * redTransform = createColorTransform(colorConfig["red"]); - RgbChannelTransform * greenTransform = createColorTransform(colorConfig["green"]); - RgbChannelTransform * blueTransform = createColorTransform(colorConfig["blue"]); - - HsvTransform * hsvTransform = createHsvTransform(colorConfig["hsv"]); - transform->addTransform(id, *redTransform, *greenTransform, *blueTransform, *hsvTransform); - transform->setTransformForLed(id, 0, ledCnt-1); - - delete redTransform; - delete greenTransform; - delete blueTransform; + ColorTransform * colorTransform = createColorTransform(colorConfig); + transform->addTransform(colorTransform); + transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1); + } + else if (!transformConfig.isArray()) + { + ColorTransform * colorTransform = createColorTransform(transformConfig); + transform->addTransform(colorTransform); + transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1); } else { + const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + for (Json::UInt i = 0; i < transformConfig.size(); ++i) + { + const Json::Value & config = transformConfig[i]; + ColorTransform * colorTransform = createColorTransform(config); + transform->addTransform(colorTransform); + + const QString ledIndicesStr = config.get("leds", "").asCString(); + if (!overallExp.exactMatch(ledIndicesStr)) + { + std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl; + continue; + } + + std::cout << "ColorTransform '" << colorTransform->_id << "' => ["; + + const QStringList ledIndexList = ledIndicesStr.split(","); + for (int i=0; i 0) + { + std::cout << ", "; + } + if (ledIndexList[i].contains("-")) + { + QStringList ledIndices = ledIndexList[i].split("-"); + int startInd = ledIndices[0].toInt(); + int endInd = ledIndices[1].toInt(); + + transform->setTransformForLed(colorTransform->_id, startInd, endInd); + std::cout << startInd << "-" << endInd; + } + else + { + int index = ledIndexList[i].toInt(); + transform->setTransformForLed(colorTransform->_id, index, index); + std::cout << index; + } + } + std::cout << "]" << std::endl; + } } return transform; } @@ -188,7 +256,7 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) return new HsvTransform(saturationGain, valueGain); } -RgbChannelTransform* Hyperion::createColorTransform(const Json::Value& colorConfig) +RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig) { const double threshold = colorConfig.get("threshold", 0.0).asDouble(); const double gamma = colorConfig.get("gamma", 1.0).asDouble(); @@ -276,6 +344,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : _device(createDevice(jsonConfig["device"])), _timer() { + if (!_raw2ledTransform->verifyTransforms()) + { + throw std::runtime_error("Color transformation incorrectly set"); + } // initialize the image processor factory ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool()); @@ -336,59 +408,14 @@ void Hyperion::setColors(int priority, const std::vector& ledColors, c } } -void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::RgbChannel color, double value) +const std::vector & Hyperion::getTransformIds() const { - ColorTransform* colorTransform = _raw2ledTransform->getTransform("default"); - assert(colorTransform != nullptr); + return _raw2ledTransform->getTransformIds(); +} - // select the transform of the requested color - RgbChannelTransform * t = nullptr; - switch (color) - { - case RED: - t = &(colorTransform->_rgbRedTransform); - break; - case GREEN: - t = &(colorTransform->_rgbGreenTransform); - break; - case BLUE: - t = &(colorTransform->_rgbBlueTransform); - break; - default: - break; - } - - // set transform value - switch (transform) - { - case SATURATION_GAIN: - colorTransform->_hsvTransform.setSaturationGain(value); - break; - case VALUE_GAIN: - colorTransform->_hsvTransform.setValueGain(value); - break; - case THRESHOLD: - assert (t != nullptr); - t->setThreshold(value); - break; - case GAMMA: - assert (t != nullptr); - t->setGamma(value); - break; - case BLACKLEVEL: - assert (t != nullptr); - t->setBlacklevel(value); - break; - case WHITELEVEL: - assert (t != nullptr); - t->setWhitelevel(value); - break; - default: - assert(false); - } - - // update the led output - update(); +ColorTransform * Hyperion::getTransform(const std::string& id) +{ + return _raw2ledTransform->getTransform(id); } void Hyperion::clear(int priority) @@ -413,54 +440,6 @@ void Hyperion::clearall() update(); } -double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::RgbChannel color) const -{ - ColorTransform * colorTransform = _raw2ledTransform->getTransform("default"); - assert(colorTransform != nullptr); - - // select the transform of the requested color - RgbChannelTransform * t = nullptr; - switch (color) - { - case RED: - t = &(colorTransform->_rgbRedTransform); - break; - case GREEN: - t = &(colorTransform->_rgbGreenTransform); - break; - case BLUE: - t = &(colorTransform->_rgbBlueTransform); - break; - default: - break; - } - - // set transform value - switch (transform) - { - case SATURATION_GAIN: - return colorTransform->_hsvTransform.getSaturationGain(); - case VALUE_GAIN: - return colorTransform->_hsvTransform.getValueGain(); - case THRESHOLD: - assert (t != nullptr); - return t->getThreshold(); - case GAMMA: - assert (t != nullptr); - return t->getGamma(); - case BLACKLEVEL: - assert (t != nullptr); - return t->getBlacklevel(); - case WHITELEVEL: - assert (t != nullptr); - return t->getWhitelevel(); - default: - assert(false); - } - - return 999.0; -} - QList Hyperion::getActivePriorities() const { return _muxer.getPriorities(); diff --git a/libsrc/hyperion/MultiColorTransform.cpp b/libsrc/hyperion/MultiColorTransform.cpp index 99b81b27..d15f020e 100644 --- a/libsrc/hyperion/MultiColorTransform.cpp +++ b/libsrc/hyperion/MultiColorTransform.cpp @@ -5,7 +5,8 @@ // Hyperion includes #include "MultiColorTransform.h" -MultiColorTransform::MultiColorTransform() +MultiColorTransform::MultiColorTransform(const unsigned ledCnt) : + _ledTransforms(ledCnt, nullptr) { } @@ -18,33 +19,16 @@ MultiColorTransform::~MultiColorTransform() } } -void MultiColorTransform::addTransform(const std::string & id, - const RgbChannelTransform & redTransform, - const RgbChannelTransform & greenTransform, - const RgbChannelTransform & blueTransform, - const HsvTransform & hsvTransform) +void MultiColorTransform::addTransform(ColorTransform * transform) { - ColorTransform * transform = new ColorTransform(); - transform->_id = id; - - transform->_rgbRedTransform = redTransform; - transform->_rgbGreenTransform = greenTransform; - transform->_rgbBlueTransform = blueTransform; - - transform->_hsvTransform = hsvTransform; - + _transformIds.push_back(transform->_id); _transform.push_back(transform); } void MultiColorTransform::setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed) { assert(startLed <= endLed); - - // Make sure that there are at least enough led transforms to match the given indices - if (_ledTransforms.size() < endLed+1) - { - _ledTransforms.resize(endLed+1, nullptr); - } + assert(endLed < _ledTransforms.size()); // Get the identified transform (don't care if is nullptr) ColorTransform * transform = getTransform(id); @@ -54,15 +38,23 @@ void MultiColorTransform::setTransformForLed(const std::string& id, const unsign } } -std::vector MultiColorTransform::getTransformIds() +bool MultiColorTransform::verifyTransforms() const { - // Create the list on the fly - std::vector transformIds; - for (ColorTransform* transform : _transform) + bool allLedsSet = true; + for (unsigned iLed=0; iLed<_ledTransforms.size(); ++iLed) { - transformIds.push_back(transform->_id); + if (_ledTransforms[iLed] == nullptr) + { + std::cerr << "No transform set for " << iLed << std::endl; + allLedsSet = false; + } } - return transformIds; + return allLedsSet; +} + +const std::vector & MultiColorTransform::getTransformIds() +{ + return _transformIds; } ColorTransform* MultiColorTransform::getTransform(const std::string& id) @@ -85,7 +77,7 @@ std::vector MultiColorTransform::applyTransform(const std::vector ledColors(rawColors); - const size_t itCnt = std::min(_transform.size(), rawColors.size()); + const size_t itCnt = std::min(_ledTransforms.size(), rawColors.size()); for (size_t i=0; i -#include -#include - -struct ColorTransform -{ - std::string _id; - /// The RED-Channel (RGB) transform - RgbChannelTransform _rgbRedTransform; - /// The GREEN-Channel (RGB) transform - RgbChannelTransform _rgbGreenTransform; - /// The BLUE-Channel (RGB) transform - RgbChannelTransform _rgbBlueTransform; - /// The HSV Transform for applying Saturation and Value transforms - HsvTransform _hsvTransform; -}; +// Hyperion includes +#include /// /// The LedColorTransform is responsible for performing color transformation from 'raw' colors @@ -29,22 +16,25 @@ struct ColorTransform class MultiColorTransform { public: - MultiColorTransform(); + MultiColorTransform(const unsigned ledCnt); ~MultiColorTransform(); - void addTransform(const std::string & id, - const RgbChannelTransform & redTransform, - const RgbChannelTransform & greenTransform, - const RgbChannelTransform & blueTransform, - const HsvTransform & hsvTransform); + /** + * Adds a new ColorTransform to this MultiColorTransform + * + * @param transform The new ColorTransform (ownership is transfered) + */ + void addTransform(ColorTransform * transform); void setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed); + bool verifyTransforms() const; + /// /// Returns the identifier of all the unique ColorTransform /// /// @return The list with unique id's of the ColorTransforms - std::vector getTransformIds(); + const std::vector & getTransformIds(); /// /// Returns the pointer to the ColorTransform with the given id @@ -65,6 +55,9 @@ public: std::vector applyTransform(const std::vector& rawColors); private: + /// List with transform ids + std::vector _transformIds; + /// List with unique ColorTransforms std::vector _transform; diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 1c99b13d..cd5894db 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -12,9 +12,10 @@ #include // hyperion util includes -#include "hyperion/ImageProcessorFactory.h" -#include "hyperion/ImageProcessor.h" -#include "utils/ColorRgb.h" +#include +#include +#include +#include // project includes #include "JsonClientConnection.h" @@ -173,25 +174,39 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &message) } // collect transform information - Json::Value & transform = info["transform"]; - transform["saturationGain"] = _hyperion->getTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID); - transform["valueGain"] = _hyperion->getTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID); - Json::Value & threshold = transform["threshold"]; - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::RED)); - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::GREEN)); - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::BLUE)); - Json::Value & gamma = transform["gamma"]; - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::RED)); - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::GREEN)); - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::BLUE)); - Json::Value & blacklevel = transform["blacklevel"]; - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::RED)); - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN)); - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE)); - Json::Value & whitelevel = transform["whitelevel"]; - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::RED)); - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::GREEN)); - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::BLUE)); + Json::Value & transformArray = info["transform"]; + for (const std::string& transformId : _hyperion->getTransformIds()) + { + const ColorTransform * colorTransform = _hyperion->getTransform(transformId); + if (colorTransform == nullptr) + { + std::cerr << "Incorrect color transform id: " << transformId << std::endl; + continue; + } + + Json::Value & transform = transformArray.append(Json::Value()); + transform["id"] = transformId; + + transform["saturationGain"] = colorTransform->_hsvTransform.getSaturationGain(); + transform["valueGain"] = colorTransform->_hsvTransform.getValueGain(); + + Json::Value & threshold = transform["threshold"]; + threshold.append(colorTransform->_rgbRedTransform.getThreshold()); + threshold.append(colorTransform->_rgbGreenTransform.getThreshold()); + threshold.append(colorTransform->_rgbBlueTransform.getThreshold()); + Json::Value & gamma = transform["gamma"]; + gamma.append(colorTransform->_rgbRedTransform.getGamma()); + gamma.append(colorTransform->_rgbGreenTransform.getGamma()); + gamma.append(colorTransform->_rgbBlueTransform.getGamma()); + Json::Value & blacklevel = transform["blacklevel"]; + blacklevel.append(colorTransform->_rgbRedTransform.getBlacklevel()); + blacklevel.append(colorTransform->_rgbGreenTransform.getBlacklevel()); + blacklevel.append(colorTransform->_rgbBlueTransform.getBlacklevel()); + Json::Value & whitelevel = transform["whitelevel"]; + whitelevel.append(colorTransform->_rgbRedTransform.getWhitelevel()); + whitelevel.append(colorTransform->_rgbGreenTransform.getWhitelevel()); + whitelevel.append(colorTransform->_rgbBlueTransform.getWhitelevel()); + } // send the result sendMessage(result); @@ -222,46 +237,54 @@ void JsonClientConnection::handleTransformCommand(const Json::Value &message) { const Json::Value & transform = message["transform"]; + const std::string transformId = transform.get("id", _hyperion->getTransformIds().front()).asString(); + ColorTransform * colorTransform = _hyperion->getTransform(transformId); + if (colorTransform == nullptr) + { + //sendErrorReply(std::string("Incorrect transform identifier: ") + transformId); + return; + } + if (transform.isMember("saturationGain")) { - _hyperion->setTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID, transform["saturationGain"].asDouble()); + colorTransform->_hsvTransform.setSaturationGain(transform["saturationGain"].asDouble()); } if (transform.isMember("valueGain")) { - _hyperion->setTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID, transform["valueGain"].asDouble()); + colorTransform->_hsvTransform.setValueGain(transform["valueGain"].asDouble()); } if (transform.isMember("threshold")) { - const Json::Value & threshold = transform["threshold"]; - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["threshold"]; + colorTransform->_rgbRedTransform .setThreshold(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setThreshold(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setThreshold(values[2u].asDouble()); } if (transform.isMember("gamma")) { - const Json::Value & threshold = transform["gamma"]; - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["gamma"]; + colorTransform->_rgbRedTransform .setGamma(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setGamma(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setGamma(values[2u].asDouble()); } if (transform.isMember("blacklevel")) { - const Json::Value & threshold = transform["blacklevel"]; - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["blacklevel"]; + colorTransform->_rgbRedTransform .setBlacklevel(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setBlacklevel(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setBlacklevel(values[2u].asDouble()); } if (transform.isMember("whitelevel")) { - const Json::Value & threshold = transform["whitelevel"]; - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["whitelevel"]; + colorTransform->_rgbRedTransform .setWhitelevel(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setWhitelevel(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setWhitelevel(values[2u].asDouble()); } sendSuccessReply(); diff --git a/libsrc/jsonserver/schema/schema-transform.json b/libsrc/jsonserver/schema/schema-transform.json index 26fdf787..a135e12f 100644 --- a/libsrc/jsonserver/schema/schema-transform.json +++ b/libsrc/jsonserver/schema/schema-transform.json @@ -1,68 +1,72 @@ { - "type":"object", - "required":true, - "properties":{ - "command": { - "type" : "string", - "required" : true, - "enum" : ["transform"] - }, - "transform": { - "type": "object", - "required": true, - "properties": { - "saturationGain" : { - "type" : "double", - "required" : false, - "minimum" : 0.0 - }, - "valueGain" : { - "type" : "double", - "required" : false, - "minimum" : 0.0 - }, - "threshold": { - "type": "array", - "required": false, - "items" : { - "type": "double", - "minimum": 0.0, - "maximum": 1.0 - }, - "minItems": 3, - "maxItems": 3 - }, - "gamma": { - "type": "array", - "required": false, - "items" : { - "type": "double", - "minimum": 0.0 - }, - "minItems": 3, - "maxItems": 3 - }, - "blacklevel": { - "type": "array", - "required": false, - "items" : { - "type": "double" - }, - "minItems": 3, - "maxItems": 3 - }, - "whitelevel": { - "type": "array", - "required": false, - "items" : { - "type": "double" - }, - "minItems": 3, - "maxItems": 3 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false + "type":"object", + "required":true, + "properties":{ + "command": { + "type" : "string", + "required" : true, + "enum" : ["transform"] + }, + "transform": { + "type": "object", + "required": true, + "properties": { + "id" : { + "type" : "string", + "required" : false + }, + "saturationGain" : { + "type" : "double", + "required" : false, + "minimum" : 0.0 + }, + "valueGain" : { + "type" : "double", + "required" : false, + "minimum" : 0.0 + }, + "threshold": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0, + "maximum": 1.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "gamma": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "blacklevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + }, + "whitelevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp index d742daaa..641c7681 100644 --- a/src/hyperion-remote/JsonConnection.cpp +++ b/src/hyperion-remote/JsonConnection.cpp @@ -160,7 +160,7 @@ void JsonConnection::clearAll() parseReply(reply); } -void JsonConnection::setTransform(double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) +void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) { std::cout << "Set color transforms" << std::endl; @@ -169,6 +169,11 @@ void JsonConnection::setTransform(double * saturation, double * value, ColorTran command["command"] = "transform"; Json::Value & transform = command["transform"]; + if (transformId != nullptr) + { + transform["id"] = *transformId; + } + if (saturation != nullptr) { transform["saturationGain"] = *saturation; diff --git a/src/hyperion-remote/JsonConnection.h b/src/hyperion-remote/JsonConnection.h index 33fc5b4a..6bd358b5 100644 --- a/src/hyperion-remote/JsonConnection.h +++ b/src/hyperion-remote/JsonConnection.h @@ -76,6 +76,7 @@ public: /// /// @note Note that providing a NULL will leave the settings on the server unchanged /// + /// @param transformId The identifier of the transform to set /// @param saturation The HSV saturation gain /// @param value The HSV value gain /// @param threshold The threshold @@ -84,6 +85,7 @@ public: /// @param whitelevel The whitelevel /// void setTransform( + std::string * transformId, double * saturation, double * value, ColorTransformValues * threshold, diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index bbe4f408..b290b4f2 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -45,6 +45,7 @@ int main(int argc, char * argv[]) SwitchParameter<> & argServerInfo = parameters.add >('l', "list" , "List server info"); SwitchParameter<> & argClear = parameters.add >('x', "clear" , "Clear data for the priority channel provided by the -p option"); SwitchParameter<> & argClearAll = parameters.add >(0x0, "clearall" , "Clear data for all active priority channels"); + StringParameter & argId = parameters.add ('q', "qualifier" , "Identifier(qualifier) of the transform to set"); DoubleParameter & argSaturation = parameters.add ('s', "saturation", "Set the HSV saturation gain of the leds"); DoubleParameter & argValue = parameters.add ('v', "value" , "Set the HSV value gain of the leds"); TransformParameter & argGamma = parameters.add('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)"); @@ -83,6 +84,7 @@ int main(int argc, char * argv[]) std::cerr << " " << argClear.usageLine() << std::endl; std::cerr << " " << argClearAll.usageLine() << std::endl; std::cerr << "or one or more of the available color transformations:" << std::endl; + std::cerr << " " << argId.usageLine() << std::endl; std::cerr << " " << argSaturation.usageLine() << std::endl; std::cerr << " " << argValue.usageLine() << std::endl; std::cerr << " " << argThreshold.usageLine() << std::endl; @@ -119,9 +121,11 @@ int main(int argc, char * argv[]) } else if (colorTransform) { + std::string transId; double saturation, value; ColorTransformValues threshold, gamma, blacklevel, whitelevel; + if (argId.isSet()) transId = argId.getValue(); if (argSaturation.isSet()) saturation = argSaturation.getValue(); if (argValue.isSet()) value = argValue.getValue(); if (argThreshold.isSet()) threshold = argThreshold.getValue(); @@ -130,6 +134,7 @@ int main(int argc, char * argv[]) if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue(); connection.setTransform( + argId.isSet() ? &transId : nullptr, argSaturation.isSet() ? &saturation : nullptr, argValue.isSet() ? &value : nullptr, argThreshold.isSet() ? &threshold : nullptr,