diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index dedf43f1..53c013ce 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -268,6 +268,7 @@ public: * @return The constructed ledstring */ static LedString createLedString(const Json::Value & ledsConfig, const ColorOrder deviceOrder); + static LedString createLedStringClone(const Json::Value & ledsConfig, const ColorOrder deviceOrder); static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig); static MultiColorCorrection * createLedColorsTemperature(const unsigned ledCnt, const Json::Value & colorTemperatureConfig); @@ -312,6 +313,10 @@ private: /// The specifiation of the led frame construction and picture integration LedString _ledString; + /// specifiation of cloned leds + LedString _ledStringClone; + + std::vector _ledStringColorOrder; /// The priority muxer PriorityMuxer _muxer; @@ -368,4 +373,5 @@ private: /// holds the current priority channel that is manualy selected int _currentSourcePriority; + }; diff --git a/include/hyperion/LedString.h b/include/hyperion/LedString.h index 2c9a0cb3..d8af5a05 100644 --- a/include/hyperion/LedString.h +++ b/include/hyperion/LedString.h @@ -97,6 +97,8 @@ struct Led double minY_frac; /// The maximum horizontal scan line included for this leds color double maxY_frac; + /// id to clone + int clone; /// the color order ColorOrder colorOrder; }; diff --git a/libsrc/effectengine/Effect.cpp b/libsrc/effectengine/Effect.cpp index 4783e8f2..b5a8b7f9 100644 --- a/libsrc/effectengine/Effect.cpp +++ b/libsrc/effectengine/Effect.cpp @@ -50,18 +50,18 @@ void Effect::registerHyperionExtensionModule() PyImport_AppendInittab("hyperion", &PyInit_hyperion); } -Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args) : - QThread(), - _mainThreadState(mainThreadState), - _priority(priority), - _timeout(timeout), - _script(script), - _args(args), - _endTime(-1), - _interpreterThreadState(nullptr), - _abortRequested(false), - _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), - _colors() +Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args) + : QThread() + , _mainThreadState(mainThreadState) + , _priority(priority) + , _timeout(timeout) + , _script(script) + , _args(args) + , _endTime(-1) + , _interpreterThreadState(nullptr) + , _abortRequested(false) + , _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()) + , _colors() { _colors.resize(_imageProcessor->getLedCount(), ColorRgb::BLACK); diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp index 93725c92..efe4676d 100644 --- a/libsrc/effectengine/EffectEngine.cpp +++ b/libsrc/effectengine/EffectEngine.cpp @@ -18,12 +18,12 @@ #include "Effect.h" #include "HyperionConfig.h" -EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectConfig) : - _hyperion(hyperion), - _availableEffects(), - _activeEffects(), - _mainThreadState(nullptr), - _log(Logger::getInstance("EFFECTENGINE")) +EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectConfig) + : _hyperion(hyperion) + , _availableEffects() + , _activeEffects() + , _mainThreadState(nullptr) + , _log(Logger::getInstance("EFFECTENGINE")) { qRegisterMetaType>("std::vector"); diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index f35bb27b..a33fef71 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -54,31 +54,7 @@ Hyperion* Hyperion::getInstance() ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig) { - std::string order = deviceConfig.get("colorOrder", "rgb").asString(); - if (order == "bgr") - { - return ORDER_BGR; - } - if (order == "rbg") - { - return ORDER_RBG; - } - if (order == "brg") - { - return ORDER_BRG; - } - if (order == "gbr") - { - return ORDER_GBR; - } - if (order == "grb") - { - return ORDER_GRB; - } - - WarningIf( order != "rgb", Logger::getInstance("Core"), "Unknown color order defined (%s). Using RGB.", order.c_str()); - - return ORDER_RGB; + return stringToColorOrder( deviceConfig.get("colorOrder", "rgb").asString() ); } ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig) @@ -443,40 +419,81 @@ RgbChannelAdjustment* Hyperion::createRgbChannelAdjustment(const Json::Value& co LedString Hyperion::createLedString(const Json::Value& ledsConfig, const ColorOrder deviceOrder) { LedString ledString; - const std::string deviceOrderStr = colorOrderToString(deviceOrder); + int maxLedId = ledsConfig.size(); for (const Json::Value& ledConfig : ledsConfig) { Led led; led.index = ledConfig["index"].asInt(); - - const Json::Value& hscanConfig = ledConfig["hscan"]; - const Json::Value& vscanConfig = ledConfig["vscan"]; - led.minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble())); - led.maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble())); - led.minY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble())); - led.maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble())); - - // Fix if the user swapped min and max - if (led.minX_frac > led.maxX_frac) + led.clone = ledConfig.get("clone",-1).asInt(); + if ( led.clone < -1 || led.clone >= maxLedId ) { - std::swap(led.minX_frac, led.maxX_frac); - } - if (led.minY_frac > led.maxY_frac) - { - std::swap(led.minY_frac, led.maxY_frac); + Warning(Logger::getInstance("Core"), "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone); + led.clone = -1; } - // Get the order of the rgb channels for this led (default is device order) - const std::string ledOrderStr = ledConfig.get("colorOrder", deviceOrderStr).asString(); - led.colorOrder = stringToColorOrder(ledOrderStr); + if ( led.clone < 0 ) + { + const Json::Value& hscanConfig = ledConfig["hscan"]; + const Json::Value& vscanConfig = ledConfig["vscan"]; + led.minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble())); + led.maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble())); + led.minY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble())); + led.maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble())); + // Fix if the user swapped min and max + if (led.minX_frac > led.maxX_frac) + { + std::swap(led.minX_frac, led.maxX_frac); + } + if (led.minY_frac > led.maxY_frac) + { + std::swap(led.minY_frac, led.maxY_frac); + } - ledString.leds().push_back(led); + // Get the order of the rgb channels for this led (default is device order) + led.colorOrder = stringToColorOrder(ledConfig.get("colorOrder", deviceOrderStr).asString()); + ledString.leds().push_back(led); + } } // Make sure the leds are sorted (on their indices) std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; }); + return ledString; +} +LedString Hyperion::createLedStringClone(const Json::Value& ledsConfig, const ColorOrder deviceOrder) +{ + LedString ledString; + const std::string deviceOrderStr = colorOrderToString(deviceOrder); + int maxLedId = ledsConfig.size(); + for (const Json::Value& ledConfig : ledsConfig) + { + Led led; + led.index = ledConfig["index"].asInt(); + led.clone = ledConfig.get("clone",-1).asInt(); + if ( led.clone < -1 || led.clone >= maxLedId ) + { + Warning(Logger::getInstance("Core"), "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone); + led.clone = -1; + } + + if ( led.clone >= 0 ) + { + Debug(Logger::getInstance("Core"), "LED %d: clone from led %d", led.index, led.clone); + led.minX_frac = 0; + led.maxX_frac = 0; + led.minY_frac = 0; + led.maxY_frac = 0; + // Get the order of the rgb channels for this led (default is device order) + led.colorOrder = stringToColorOrder(ledConfig.get("colorOrder", deviceOrderStr).asString()); + + ledString.leds().push_back(led); + } + + } + + // Make sure the leds are sorted (on their indices) + std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; }); return ledString; } @@ -543,6 +560,7 @@ MessageForwarder * Hyperion::getForwarder() Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))) + , _ledStringClone(createLedStringClone(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))) , _muxer(_ledString.leds().size()) , _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])) , _raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"])) @@ -595,7 +613,7 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile) QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update())); // create the effect engine - _effectEngine = new EffectEngine(this, jsonConfig["effects"]); + _effectEngine = new EffectEngine(this,jsonConfig["effects"]); unsigned int hwLedCount = jsonConfig["device"].get("ledCount",getLedCount()).asUInt(); _hwLedCount = std::max(hwLedCount, getLedCount()); @@ -867,14 +885,32 @@ void Hyperion::update() if (_adjustmentEnabled) _raw2ledAdjustment->applyAdjustment(_ledBuffer); if (_temperatureEnabled) _raw2ledTemperature->applyCorrection(_ledBuffer); - const std::vector& leds = _ledString.leds(); - + // init colororder vector, if nempty + if (_ledStringColorOrder.empty()) + { + for (Led& led : _ledString.leds()) + { + _ledStringColorOrder.push_back(led.colorOrder); + } + for (Led& led : _ledStringClone.leds()) + { + _ledStringColorOrder.insert(_ledStringColorOrder.begin() + led.index, led.colorOrder); + } + } + + // insert cloned leds into buffer + for (Led& led : _ledStringClone.leds()) + { + _ledBuffer.insert(_ledBuffer.begin() + led.index, _ledBuffer.at(led.clone)); + } + int i = 0; for (ColorRgb& color : _ledBuffer) { - const ColorOrder ledColorOrder = leds.at(i).colorOrder; + //const ColorOrder ledColorOrder = leds.at(i).colorOrder; + // correct the color byte order - switch (ledColorOrder) + switch (_ledStringColorOrder.at(i)) { case ORDER_RGB: // leave as it is diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index 050f7fa4..1bc3eb82 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -9,7 +9,7 @@ "properties" : { "level" : - { + { "enum" : ["silent", "warn", "verbose", "debug"] } }, @@ -33,19 +33,19 @@ }, "output" : { - "type" : "string", - "required" : true + "type" : "string" }, "rate" : { "type" : "integer", - "required" : false, "minimum" : 0 }, "colorOrder" : { - "type" : "string", - "required" : false + "type": + { + "enum" : ["bgr", "rbg", "brg", "gbr", "grb"] + } } }, "additionalProperties" : true @@ -852,20 +852,27 @@ "type":"integer", "required":true }, + "clone": + { + "type":"integer" + }, "hscan": { "type":"object", - "required":true, "properties": { "minimum": { "type":"number", + "minimum" : 0, + "maximum" : 1, "required":true }, "maximum": { "type":"number", + "minimum" : 0, + "maximum" : 1, "required":true } }, @@ -874,17 +881,20 @@ "vscan": { "type":"object", - "required":true, "properties": { "minimum": { "type":"number", + "minimum" : 0, + "maximum" : 1, "required":true }, "maximum": { "type":"number", + "minimum" : 0, + "maximum" : 1, "required":true } }, @@ -892,8 +902,10 @@ }, "colorOrder": { - "type":"string", - "required":false + "type": + { + "enum" : ["bgr", "rbg", "brg", "gbr", "grb"] + } } }, "additionalProperties" : false diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 21b9d113..02ede739 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -2,6 +2,7 @@ #include #include #include +#include // Build configuration #include @@ -62,260 +63,265 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) std::transform(type.begin(), type.end(), type.begin(), ::tolower); LedDevice* device = nullptr; - if (false) {} - else if (type == "adalight") + try { - device = new LedDeviceAdalight( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt(), - deviceConfig.get("delayAfterConnect",500).asInt() - ); - } - else if (type == "adalightapa102") - { - device = new LedDeviceAdalightApa102( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt(), - deviceConfig.get("delayAfterConnect",500).asInt() - ); - } -#ifdef ENABLE_SPIDEV - else if (type == "lpd6803" || type == "ldp6803") - { - device = new LedDeviceLpd6803( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "lpd8806" || type == "ldp8806") - { - device = new LedDeviceLpd8806( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "p9813") - { - device = new LedDeviceP9813( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "apa102") - { - device = new LedDeviceAPA102( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "ws2801" || type == "lightberry") - { - device = new LedDeviceWs2801( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt(), - deviceConfig.get("latchtime",500000).asInt() - ); - } - else if (type == "ws2812spi") - { - device = new LedDeviceWs2812SPI( - deviceConfig["output"].asString(), - deviceConfig.get("rate",2857143).asInt() - ); - } - else if (type == "sk6812rgbw-spi") - { - device = new LedDeviceSk6812SPI( - deviceConfig["output"].asString(), - deviceConfig.get("rate",2857143).asInt(), - deviceConfig.get("white_algorithm","").asString() - ); - } -#endif -#ifdef ENABLE_TINKERFORGE - else if (type=="tinkerforge") - { - device = new LedDeviceTinkerforge( - deviceConfig.get("output", "127.0.0.1").asString(), - deviceConfig.get("port", 4223).asInt(), - deviceConfig["uid"].asString(), - deviceConfig["rate"].asInt() - ); - - } -#endif - else if (type == "rawhid") - { - const int delay_ms = deviceConfig["delayAfterConnect"].asInt(); - auto VendorIdString = deviceConfig.get("VID", "0x2341").asString(); - auto ProductIdString = deviceConfig.get("PID", "0x8036").asString(); - - // Convert HEX values to integer - auto VendorId = std::stoul(VendorIdString, nullptr, 16); - auto ProductId = std::stoul(ProductIdString, nullptr, 16); - - device = new LedDeviceRawHID(VendorId, ProductId, delay_ms); - } - else if (type == "lightpack") - { - device = new LedDeviceLightpack( - deviceConfig.get("output", "").asString() - ); - } - else if (type == "multi-lightpack") - { - device = new LedDeviceMultiLightpack(); - } - else if (type == "paintpack") - { - const int delay_ms = deviceConfig["delayAfterConnect"].asInt(); - auto VendorIdString = deviceConfig.get("VID", "0x0EBF").asString(); - auto ProductIdString = deviceConfig.get("PID", "0x0025").asString(); - - // Convert HEX values to integer - auto VendorId = std::stoul(VendorIdString, nullptr, 16); - auto ProductId = std::stoul(ProductIdString, nullptr, 16); - - device = new LedDevicePaintpack(VendorId, ProductId, delay_ms); - } - else if (type == "piblaster") - { - const std::string output = deviceConfig.get("output", "").asString(); - const std::string assignment = deviceConfig.get("assignment", "").asString(); - const Json::Value gpioMapping = deviceConfig.get("gpiomap", Json::nullValue); - - if (! assignment.empty()) + if (false) {} + else if (type == "adalight") { - throw std::runtime_error("Piblaster: The piblaster configuration syntax has changed in this version."); + device = new LedDeviceAdalight( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt(), + deviceConfig.get("delayAfterConnect",500).asInt() + ); } - if (gpioMapping.isNull()) + else if (type == "adalightapa102") { - throw std::runtime_error("Piblaster: no gpiomap defined."); + device = new LedDeviceAdalightApa102( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt(), + deviceConfig.get("delayAfterConnect",500).asInt() + ); } - device = new LedDevicePiBlaster(output, gpioMapping); - } - else if (type == "sedu") - { - device = new LedDeviceSedu( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "hyperion-usbasp-ws2801") - { - device = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2801); - } - else if (type == "hyperion-usbasp-ws2812") - { - device = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2812); - } - else if (type == "philipshue") - { - const std::string output = deviceConfig["output"].asString(); - const std::string username = deviceConfig.get("username", "newdeveloper").asString(); - const bool switchOffOnBlack = deviceConfig.get("switchOffOnBlack", true).asBool(); - const int transitiontime = deviceConfig.get("transitiontime", 1).asInt(); - std::vector lightIds; - for (Json::Value::ArrayIndex i = 0; i < deviceConfig["lightIds"].size(); i++) { - lightIds.push_back(deviceConfig["lightIds"][i].asInt()); + #ifdef ENABLE_SPIDEV + else if (type == "lpd6803" || type == "ldp6803") + { + device = new LedDeviceLpd6803( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); } - device = new LedDevicePhilipsHue(output, username, switchOffOnBlack, transitiontime, lightIds); - } - else if (type == "atmoorb") - { - const std::string output = deviceConfig["output"].asString(); - const bool useOrbSmoothing = deviceConfig.get("useOrbSmoothing", false).asBool(); - const int transitiontime = deviceConfig.get("transitiontime", 1).asInt(); - const int skipSmoothingDiff = deviceConfig.get("skipSmoothingDiff", 0).asInt(); - const int port = deviceConfig.get("port", 1).asInt(); - const int numLeds = deviceConfig.get("numLeds", 1).asInt(); - const std::string orbId = deviceConfig["orbIds"].asString(); - std::vector orbIds; + else if (type == "lpd8806" || type == "ldp8806") + { + device = new LedDeviceLpd8806( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); + } + else if (type == "p9813") + { + device = new LedDeviceP9813( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); + } + else if (type == "apa102") + { + device = new LedDeviceAPA102( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); + } + else if (type == "ws2801" || type == "lightberry") + { + device = new LedDeviceWs2801( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt(), + deviceConfig.get("latchtime",500000).asInt() + ); + } + else if (type == "ws2812spi") + { + device = new LedDeviceWs2812SPI( + deviceConfig["output"].asString(), + deviceConfig.get("rate",2857143).asInt() + ); + } + else if (type == "sk6812rgbw-spi") + { + device = new LedDeviceSk6812SPI( + deviceConfig["output"].asString(), + deviceConfig.get("rate",2857143).asInt(), + deviceConfig.get("white_algorithm","").asString() + ); + } + #endif + #ifdef ENABLE_TINKERFORGE + else if (type=="tinkerforge") + { + device = new LedDeviceTinkerforge( + deviceConfig.get("output", "127.0.0.1").asString(), + deviceConfig.get("port", 4223).asInt(), + deviceConfig["uid"].asString(), + deviceConfig["rate"].asInt() + ); - // If we find multiple Orb ids separate them and add to list - const std::string separator (","); - if (orbId.find(separator) != std::string::npos) { - std::stringstream ss(orbId); - std::vector output; - unsigned int i; - while (ss >> i) { - orbIds.push_back(i); - if (ss.peek() == ',' || ss.peek() == ' ') - ss.ignore(); - } + } + #endif + else if (type == "rawhid") + { + const int delay_ms = deviceConfig["delayAfterConnect"].asInt(); + auto VendorIdString = deviceConfig.get("VID", "0x2341").asString(); + auto ProductIdString = deviceConfig.get("PID", "0x8036").asString(); + + // Convert HEX values to integer + auto VendorId = std::stoul(VendorIdString, nullptr, 16); + auto ProductId = std::stoul(ProductIdString, nullptr, 16); + + device = new LedDeviceRawHID(VendorId, ProductId, delay_ms); + } + else if (type == "lightpack") + { + device = new LedDeviceLightpack( + deviceConfig.get("output", "").asString() + ); + } + else if (type == "multi-lightpack") + { + device = new LedDeviceMultiLightpack(); + } + else if (type == "paintpack") + { + const int delay_ms = deviceConfig["delayAfterConnect"].asInt(); + auto VendorIdString = deviceConfig.get("VID", "0x0EBF").asString(); + auto ProductIdString = deviceConfig.get("PID", "0x0025").asString(); + + // Convert HEX values to integer + auto VendorId = std::stoul(VendorIdString, nullptr, 16); + auto ProductId = std::stoul(ProductIdString, nullptr, 16); + + device = new LedDevicePaintpack(VendorId, ProductId, delay_ms); + } + else if (type == "piblaster") + { + const std::string output = deviceConfig.get("output", "").asString(); + const std::string assignment = deviceConfig.get("assignment", "").asString(); + const Json::Value gpioMapping = deviceConfig.get("gpiomap", Json::nullValue); + + if (! assignment.empty()) + { + throw std::runtime_error("Piblaster: The piblaster configuration syntax has changed in this version."); + } + if (gpioMapping.isNull()) + { + throw std::runtime_error("Piblaster: no gpiomap defined."); + } + device = new LedDevicePiBlaster(output, gpioMapping); + } + else if (type == "sedu") + { + device = new LedDeviceSedu( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); + } + else if (type == "hyperion-usbasp-ws2801") + { + device = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2801); + } + else if (type == "hyperion-usbasp-ws2812") + { + device = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2812); + } + else if (type == "philipshue") + { + const std::string output = deviceConfig["output"].asString(); + const std::string username = deviceConfig.get("username", "newdeveloper").asString(); + const bool switchOffOnBlack = deviceConfig.get("switchOffOnBlack", true).asBool(); + const int transitiontime = deviceConfig.get("transitiontime", 1).asInt(); + std::vector lightIds; + for (Json::Value::ArrayIndex i = 0; i < deviceConfig["lightIds"].size(); i++) { + lightIds.push_back(deviceConfig["lightIds"][i].asInt()); + } + device = new LedDevicePhilipsHue(output, username, switchOffOnBlack, transitiontime, lightIds); + } + else if (type == "atmoorb") + { + const std::string output = deviceConfig["output"].asString(); + const bool useOrbSmoothing = deviceConfig.get("useOrbSmoothing", false).asBool(); + const int transitiontime = deviceConfig.get("transitiontime", 1).asInt(); + const int skipSmoothingDiff = deviceConfig.get("skipSmoothingDiff", 0).asInt(); + const int port = deviceConfig.get("port", 1).asInt(); + const int numLeds = deviceConfig.get("numLeds", 1).asInt(); + const std::string orbId = deviceConfig["orbIds"].asString(); + std::vector orbIds; + + // If we find multiple Orb ids separate them and add to list + const std::string separator (","); + if (orbId.find(separator) != std::string::npos) { + std::stringstream ss(orbId); + std::vector output; + unsigned int i; + while (ss >> i) { + orbIds.push_back(i); + if (ss.peek() == ',' || ss.peek() == ' ') + ss.ignore(); + } + } + else + { + orbIds.push_back(atoi(orbId.c_str())); + } + + device = new LedDeviceAtmoOrb(output, useOrbSmoothing, transitiontime, skipSmoothingDiff, port, numLeds, orbIds); + } + else if (type == "fadecandy") + { + device = new LedDeviceFadeCandy(deviceConfig); + } + else if (type == "udp") + { + device = new LedDeviceUdp( + deviceConfig["output"].asString(), + deviceConfig["protocol"].asInt(), + deviceConfig["maxpacket"].asInt() + ); + } + else if (type == "udpraw") + { + device = new LedDeviceUdpRaw( + deviceConfig["output"].asString(), + deviceConfig.get("latchtime",500000).asInt() + ); + } + else if (type == "tpm2") + { + device = new LedDeviceTpm2( + deviceConfig["output"].asString(), + deviceConfig["rate"].asInt() + ); + } + else if (type == "atmo") + { + device = new LedDeviceAtmo( + deviceConfig["output"].asString(), + 38400 + ); + } + #ifdef ENABLE_WS2812BPWM + else if (type == "ws2812b") + { + device = new LedDeviceWS2812b(); + } + #endif + #ifdef ENABLE_WS281XPWM + else if (type == "ws281x") + { + device = new LedDeviceWS281x( + deviceConfig.get("gpio", 18).asInt(), + deviceConfig.get("leds", 256).asInt(), + deviceConfig.get("freq", (Json::UInt)800000ul).asInt(), + deviceConfig.get("dmanum", 5).asInt(), + deviceConfig.get("pwmchannel", 0).asInt(), + deviceConfig.get("invert", 0).asInt(), + deviceConfig.get("rgbw", 0).asInt(), + deviceConfig.get("white_algorithm","").asString() + ); + } + #endif + else if (type == "file") + { + device = new LedDeviceFile( deviceConfig.get("output", "/dev/null").asString() ); } else { - orbIds.push_back(atoi(orbId.c_str())); + throw std::runtime_error("unknown device"); } - - device = new LedDeviceAtmoOrb(output, useOrbSmoothing, transitiontime, skipSmoothingDiff, port, numLeds, orbIds); } - else if (type == "fadecandy") + catch(std::exception e) { - device = new LedDeviceFadeCandy(deviceConfig); - } - else if (type == "udp") - { - device = new LedDeviceUdp( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt(), - deviceConfig["protocol"].asInt(), - deviceConfig["maxpacket"].asInt() - ); - } - else if (type == "udpraw") - { - device = new LedDeviceUdpRaw( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt(), - deviceConfig.get("latchtime",500000).asInt() - ); - } - else if (type == "tpm2") - { - device = new LedDeviceTpm2( - deviceConfig["output"].asString(), - deviceConfig["rate"].asInt() - ); - } - else if (type == "atmo") - { - device = new LedDeviceAtmo( - deviceConfig["output"].asString(), - 38400 - ); - } -#ifdef ENABLE_WS2812BPWM - else if (type == "ws2812b") - { - device = new LedDeviceWS2812b(); - } -#endif -#ifdef ENABLE_WS281XPWM - else if (type == "ws281x") - { - device = new LedDeviceWS281x( - deviceConfig.get("gpio", 18).asInt(), - deviceConfig.get("leds", 256).asInt(), - deviceConfig.get("freq", (Json::UInt)800000ul).asInt(), - deviceConfig.get("dmanum", 5).asInt(), - deviceConfig.get("pwmchannel", 0).asInt(), - deviceConfig.get("invert", 0).asInt(), - deviceConfig.get("rgbw", 0).asInt(), - deviceConfig.get("white_algorithm","").asString() - ); - } -#endif - else - { - if (type != "file") - { - Error(log, "Dummy device used, because unknown device %s set.", type.c_str()); - } - device = new LedDeviceFile( - deviceConfig.get("output", "/dev/null").asString() - ); + + Error(log, "Dummy device used, because configured device '%s' throws error '%s'", type.c_str(), e.what()); + device = new LedDeviceFile( "/dev/null" ); } device->open(); diff --git a/libsrc/leddevice/LedDevicePiBlaster.cpp b/libsrc/leddevice/LedDevicePiBlaster.cpp index 102d4139..072a5be8 100644 --- a/libsrc/leddevice/LedDevicePiBlaster.cpp +++ b/libsrc/leddevice/LedDevicePiBlaster.cpp @@ -13,9 +13,9 @@ // Local LedDevice includes #include "LedDevicePiBlaster.h" -LedDevicePiBlaster::LedDevicePiBlaster(const std::string & deviceName, const Json::Value & gpioMapping) : - _deviceName(deviceName), - _fid(nullptr) +LedDevicePiBlaster::LedDevicePiBlaster(const std::string & deviceName, const Json::Value & gpioMapping) + : _deviceName(deviceName) + , _fid(nullptr) { signal(SIGPIPE, SIG_IGN); @@ -59,34 +59,25 @@ LedDevicePiBlaster::~LedDevicePiBlaster() } } -int LedDevicePiBlaster::open(bool report) +int LedDevicePiBlaster::open() { if (_fid != nullptr) { // The file pointer is already open - if (report) - { - Error( _log, "Device (%s) is already open.", _deviceName.c_str() ); - } + Error( _log, "Device (%s) is already open.", _deviceName.c_str() ); return -1; } if (!QFile::exists(_deviceName.c_str())) { - if (report) - { - Error( _log, "The device (%s) does not yet exist.", _deviceName.c_str() ); - } + Error( _log, "The device (%s) does not yet exist.", _deviceName.c_str() ); return -1; } _fid = fopen(_deviceName.c_str(), "w"); if (_fid == nullptr) { - if (report) - { - Error( _log, "Failed to open device (%s). Error message: %s", _deviceName.c_str(), strerror(errno) ); - } + Error( _log, "Failed to open device (%s). Error message: %s", _deviceName.c_str(), strerror(errno) ); return -1; } @@ -98,7 +89,7 @@ int LedDevicePiBlaster::open(bool report) int LedDevicePiBlaster::write(const std::vector & ledValues) { // Attempt to open if not yet opened - if (_fid == nullptr && open(false) < 0) + if (_fid == nullptr && open() < 0) { return -1; } @@ -151,7 +142,7 @@ int LedDevicePiBlaster::write(const std::vector & ledValues) int LedDevicePiBlaster::switchOff() { // Attempt to open if not yet opened - if (_fid == nullptr && open(false) < 0) + if (_fid == nullptr && open() < 0) { return -1; } diff --git a/libsrc/leddevice/LedDevicePiBlaster.h b/libsrc/leddevice/LedDevicePiBlaster.h index ea9a9cdf..b61bc0b3 100644 --- a/libsrc/leddevice/LedDevicePiBlaster.h +++ b/libsrc/leddevice/LedDevicePiBlaster.h @@ -27,10 +27,9 @@ public: /// Attempts to open the piblaster-device. This will only succeed if the device is not yet open /// and the device is available. /// - /// @param report If true errors are writen to the standard error else silent /// @return Zero on succes else negative /// - int open(bool report = true); + int open(); /// /// Writes the colors to the PiBlaster device diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp index 480e6e29..a91e680c 100644 --- a/libsrc/leddevice/LedDeviceUdp.cpp +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -21,7 +21,7 @@ unsigned leds_per_pkt; int update_number; int fragment_number; -LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket) +LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned protocol, const unsigned maxPacket) { std::string hostname; std::string port; diff --git a/libsrc/leddevice/LedDeviceUdp.h b/libsrc/leddevice/LedDeviceUdp.h index c8e2f119..66a49a58 100644 --- a/libsrc/leddevice/LedDeviceUdp.h +++ b/libsrc/leddevice/LedDeviceUdp.h @@ -7,8 +7,8 @@ #include /// -/// Implementation of the LedDevice that write the led-colors to an -/// ASCII-textfile('/home/pi/LedDevice.out') +/// Implementation of the LedDevice that write the led-colors via udp +/// /// class LedDeviceUdp : public LedDevice { @@ -16,7 +16,7 @@ public: /// /// Constructs the test-device, which opens an output stream to the file /// - LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket); + LedDeviceUdp(const std::string& output, const unsigned protocol, const unsigned maxPacket); /// /// Destructor of this test-device @@ -36,9 +36,6 @@ public: virtual int switchOff(); private: - /// The outputstream -// std::ofstream _ofs; - - /// the number of leds (needed when switching off) - size_t mLedCount; + /// the number of leds (needed when switching off) + size_t mLedCount; }; diff --git a/libsrc/leddevice/LedDeviceUdpRaw.cpp b/libsrc/leddevice/LedDeviceUdpRaw.cpp index 7f186de0..b5061ac0 100644 --- a/libsrc/leddevice/LedDeviceUdpRaw.cpp +++ b/libsrc/leddevice/LedDeviceUdpRaw.cpp @@ -11,8 +11,8 @@ // hyperion local includes #include "LedDeviceUdpRaw.h" -LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned baudrate, const unsigned latchTime) : - LedUdpDevice(outputDevice, baudrate, latchTime), +LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned latchTime) : + LedUdpDevice(outputDevice, latchTime), mLedCount(0) { // empty diff --git a/libsrc/leddevice/LedDeviceUdpRaw.h b/libsrc/leddevice/LedDeviceUdpRaw.h index bf64e622..7e546fa4 100644 --- a/libsrc/leddevice/LedDeviceUdpRaw.h +++ b/libsrc/leddevice/LedDeviceUdpRaw.h @@ -7,21 +7,19 @@ #include "LedUdpDevice.h" /// -/// Implementation of the LedDevice interface for writing to Ws2801 led device. +/// Implementation of the LedDevice interface for sending led colors via udp. /// class LedDeviceUdpRaw : public LedUdpDevice { public: /// - /// Constructs the LedDevice for a string containing leds of the type Ws2801 + /// Constructs the LedDevice for sending led colors via udp /// - /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') - /// @param baudrate The used baudrate for writing to the output device + /// @param outputDevice hostname:port + /// @param latchTime /// - LedDeviceUdpRaw(const std::string& outputDevice, - const unsigned baudrate, - const unsigned latchTime); + LedDeviceUdpRaw(const std::string& outputDevice, const unsigned latchTime); /// /// Writes the led color values to the led-device diff --git a/libsrc/leddevice/LedSpiDevice.h b/libsrc/leddevice/LedSpiDevice.h index 299cf904..353413cf 100644 --- a/libsrc/leddevice/LedSpiDevice.h +++ b/libsrc/leddevice/LedSpiDevice.h @@ -15,7 +15,7 @@ public: /// /// Constructs the LedDevice attached to a SPI-device /// - /// @param[in] outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param[in] outputDevice The name of the output device (eg '/dev/spidev.0.0') /// @param[in] baudrate The used baudrate for writing to the output device /// @param[in] latchTime_ns The latch-time to latch in the values across the SPI-device (negative /// means no latch required) [ns] diff --git a/libsrc/leddevice/LedUdpDevice.cpp b/libsrc/leddevice/LedUdpDevice.cpp index fe63e3fa..35e074bb 100644 --- a/libsrc/leddevice/LedUdpDevice.cpp +++ b/libsrc/leddevice/LedUdpDevice.cpp @@ -3,7 +3,7 @@ #include #include #include - +#include // Linux includes #include #include @@ -15,17 +15,15 @@ // Local Hyperion includes #include "LedUdpDevice.h" -LedUdpDevice::LedUdpDevice(const std::string& output, const unsigned baudrate, const int latchTime_ns) : +LedUdpDevice::LedUdpDevice(const std::string& output, const int latchTime_ns) : _target(output), - _BaudRate_Hz(baudrate), _LatchTime_ns(latchTime_ns) { udpSocket = new QUdpSocket(); QString str = QString::fromStdString(_target); QStringList _list = str.split(":"); if (_list.size() != 2) { - Error( _log, "Error parsing hostname:port"); - exit (-1); + throw("Error parsing hostname:port"); } QHostInfo info = QHostInfo::fromName(_list.at(0)); if (!info.addresses().isEmpty()) { @@ -45,8 +43,7 @@ int LedUdpDevice::open() QHostAddress _localAddress = QHostAddress::Any; quint16 _localPort = 0; - WarningIf( !udpSocket->bind(_localAddress, _localPort), - _log, "Couldnt bind local address: %s", strerror(errno)); + WarningIf( !udpSocket->bind(_localAddress, _localPort), _log, "Couldnt bind local address: %s", strerror(errno)); return 0; } diff --git a/libsrc/leddevice/LedUdpDevice.h b/libsrc/leddevice/LedUdpDevice.h index 8c6e024e..acb00983 100644 --- a/libsrc/leddevice/LedUdpDevice.h +++ b/libsrc/leddevice/LedUdpDevice.h @@ -13,14 +13,13 @@ class LedUdpDevice : public LedDevice { public: /// - /// Constructs the LedDevice attached to a SPI-device + /// Constructs the LedDevice sendig data via udp /// - /// @param[in] outputDevice The name of the output device (eg '/etc/UdpDev.0.0') - /// @param[in] baudrate The used baudrate for writing to the output device + /// @param[in] outputDevice string hostname:port /// @param[in] latchTime_ns The latch-time to latch in the values across the SPI-device (negative /// means no latch required) [ns] /// - LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns = -1); + LedUdpDevice(const std::string& outputDevice, const int latchTime_ns = -1); /// /// Destructor of the LedDevice; closes the output device if it is open @@ -49,8 +48,6 @@ protected: private: /// The UDP destination as "host:port" const std::string _target; - /// The used baudrate of the output device for rate limiting - const int _BaudRate_Hz; /// The time which the device should be untouched after a write const int _LatchTime_ns; diff --git a/libsrc/webconfig/WebConfig.cpp b/libsrc/webconfig/WebConfig.cpp index a312fa5a..d702809c 100644 --- a/libsrc/webconfig/WebConfig.cpp +++ b/libsrc/webconfig/WebConfig.cpp @@ -4,9 +4,9 @@ WebConfig::WebConfig(QObject * parent) : QObject(parent) - , _port(WEBCONFIG_DEFAULT_PORT) , _server(nullptr) { + _port = WEBCONFIG_DEFAULT_PORT; _hyperion = Hyperion::getInstance(); const Json::Value &config = _hyperion->getJsonConfig(); _baseUrl = QString::fromStdString(WEBCONFIG_DEFAULT_PATH); diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt index 64817c83..fce4a527 100644 --- a/src/hyperion-remote/CMakeLists.txt +++ b/src/hyperion-remote/CMakeLists.txt @@ -7,8 +7,10 @@ find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) # The following I do not undrstand completely... # libQtCore.so uses some hardcoded library path inside which are incorrect after copying the file RPi file system -# Therefor, an extra path is needed on which to find the required libraries -LINK_DIRECTORIES(${LINK_DIRECTORIES} ${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) +# Therefore, an extra path is needed on which to find the required libraries +IF ( EXISTS ${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf ) + LINK_DIRECTORIES(${LINK_DIRECTORIES} ${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) +ENDIF() include_directories(${QT_INCLUDES}) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index c86da78b..f88a79a4 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -420,7 +420,7 @@ void HyperionDaemon::createSystemFrameGrabber() // framebuffer -> if nothing other applies else { - type == "framebuffer"; + type = "framebuffer"; } Info( _log, "set screen capture device to '%s'", type.constData()); } diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index 031974ad..113d7675 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -86,7 +85,6 @@ private: AmlogicWrapper* _amlGrabber; FramebufferWrapper* _fbGrabber; OsxWrapper* _osxGrabber; - WebConfig* _webConfig; Hyperion* _hyperion; unsigned _grabber_width; diff --git a/test/switchPinCtrl.c b/test/switchPinCtrl.c index 8b4eca34..3150c423 100644 --- a/test/switchPinCtrl.c +++ b/test/switchPinCtrl.c @@ -143,7 +143,7 @@ void setup_io() ); if ((long)gpio_map < 0) { - printf("mmap error %d\n", (long)gpio_map); + printf("mmap error %ld\n", (long)gpio_map); exit (-1); } gpio = (volatile unsigned *)gpio_map; @@ -166,10 +166,10 @@ void setup_io() ); - printf("SPI mapped from 0x%p to 0x%p\n",SPI0_BASE,spi0_map); + printf("SPI mapped from 0x%d to 0x%p\n",SPI0_BASE,spi0_map); if ((long)spi0_map < 0) { - printf("mmap error %d\n", (long)spi0_map); + printf("mmap error %ld\n", (long)spi0_map); exit (-1); } spi0 = (volatile unsigned *)spi0_map;