Skip to content

Commit 197af35

Browse files
authored
Clone single led color from other led (#157)
* start ledclone * led cloning: clone scan areas from original led main: show exceptions, better exit * tune json schema for new option. somwe cleanup * fix warnings and bug for framebuffer selection. thx to clang brought by new osx buikld on travis * make ledclone feature work flawlessly for effects too. Effect sees the ledstring without cloned leds. cloned leds will be inserted just before sending to leddevice additional: remove warnings and fix code style * fix warning
1 parent a56f98b commit 197af35

21 files changed

+413
-372
lines changed

include/hyperion/Hyperion.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ public slots:
268268
* @return The constructed ledstring
269269
*/
270270
static LedString createLedString(const Json::Value & ledsConfig, const ColorOrder deviceOrder);
271+
static LedString createLedStringClone(const Json::Value & ledsConfig, const ColorOrder deviceOrder);
271272

272273
static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig);
273274
static MultiColorCorrection * createLedColorsTemperature(const unsigned ledCnt, const Json::Value & colorTemperatureConfig);
@@ -312,6 +313,10 @@ private slots:
312313
/// The specifiation of the led frame construction and picture integration
313314
LedString _ledString;
314315

316+
/// specifiation of cloned leds
317+
LedString _ledStringClone;
318+
319+
std::vector<ColorOrder> _ledStringColorOrder;
315320
/// The priority muxer
316321
PriorityMuxer _muxer;
317322

@@ -368,4 +373,5 @@ private slots:
368373

369374
/// holds the current priority channel that is manualy selected
370375
int _currentSourcePriority;
376+
371377
};

include/hyperion/LedString.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ struct Led
9797
double minY_frac;
9898
/// The maximum horizontal scan line included for this leds color
9999
double maxY_frac;
100+
/// id to clone
101+
int clone;
100102
/// the color order
101103
ColorOrder colorOrder;
102104
};

libsrc/effectengine/Effect.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ void Effect::registerHyperionExtensionModule()
5050
PyImport_AppendInittab("hyperion", &PyInit_hyperion);
5151
}
5252

53-
Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args) :
54-
QThread(),
55-
_mainThreadState(mainThreadState),
56-
_priority(priority),
57-
_timeout(timeout),
58-
_script(script),
59-
_args(args),
60-
_endTime(-1),
61-
_interpreterThreadState(nullptr),
62-
_abortRequested(false),
63-
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
64-
_colors()
53+
Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args)
54+
: QThread()
55+
, _mainThreadState(mainThreadState)
56+
, _priority(priority)
57+
, _timeout(timeout)
58+
, _script(script)
59+
, _args(args)
60+
, _endTime(-1)
61+
, _interpreterThreadState(nullptr)
62+
, _abortRequested(false)
63+
, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
64+
, _colors()
6565
{
6666
_colors.resize(_imageProcessor->getLedCount(), ColorRgb::BLACK);
6767

libsrc/effectengine/EffectEngine.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
#include "Effect.h"
1919
#include "HyperionConfig.h"
2020

21-
EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectConfig) :
22-
_hyperion(hyperion),
23-
_availableEffects(),
24-
_activeEffects(),
25-
_mainThreadState(nullptr),
26-
_log(Logger::getInstance("EFFECTENGINE"))
21+
EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectConfig)
22+
: _hyperion(hyperion)
23+
, _availableEffects()
24+
, _activeEffects()
25+
, _mainThreadState(nullptr)
26+
, _log(Logger::getInstance("EFFECTENGINE"))
2727
{
2828
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
2929

libsrc/hyperion/Hyperion.cpp

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,7 @@ Hyperion* Hyperion::getInstance()
5454

5555
ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig)
5656
{
57-
std::string order = deviceConfig.get("colorOrder", "rgb").asString();
58-
if (order == "bgr")
59-
{
60-
return ORDER_BGR;
61-
}
62-
if (order == "rbg")
63-
{
64-
return ORDER_RBG;
65-
}
66-
if (order == "brg")
67-
{
68-
return ORDER_BRG;
69-
}
70-
if (order == "gbr")
71-
{
72-
return ORDER_GBR;
73-
}
74-
if (order == "grb")
75-
{
76-
return ORDER_GRB;
77-
}
78-
79-
WarningIf( order != "rgb", Logger::getInstance("Core"), "Unknown color order defined (%s). Using RGB.", order.c_str());
80-
81-
return ORDER_RGB;
57+
return stringToColorOrder( deviceConfig.get("colorOrder", "rgb").asString() );
8258
}
8359

8460
ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig)
@@ -443,40 +419,81 @@ RgbChannelAdjustment* Hyperion::createRgbChannelAdjustment(const Json::Value& co
443419
LedString Hyperion::createLedString(const Json::Value& ledsConfig, const ColorOrder deviceOrder)
444420
{
445421
LedString ledString;
446-
447422
const std::string deviceOrderStr = colorOrderToString(deviceOrder);
423+
int maxLedId = ledsConfig.size();
448424
for (const Json::Value& ledConfig : ledsConfig)
449425
{
450426
Led led;
451427
led.index = ledConfig["index"].asInt();
428+
led.clone = ledConfig.get("clone",-1).asInt();
429+
if ( led.clone < -1 || led.clone >= maxLedId )
430+
{
431+
Warning(Logger::getInstance("Core"), "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone);
432+
led.clone = -1;
433+
}
452434

453-
const Json::Value& hscanConfig = ledConfig["hscan"];
454-
const Json::Value& vscanConfig = ledConfig["vscan"];
455-
led.minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble()));
456-
led.maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble()));
457-
led.minY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble()));
458-
led.maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble()));
459-
460-
// Fix if the user swapped min and max
461-
if (led.minX_frac > led.maxX_frac)
435+
if ( led.clone < 0 )
462436
{
463-
std::swap(led.minX_frac, led.maxX_frac);
437+
const Json::Value& hscanConfig = ledConfig["hscan"];
438+
const Json::Value& vscanConfig = ledConfig["vscan"];
439+
led.minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble()));
440+
led.maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble()));
441+
led.minY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble()));
442+
led.maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble()));
443+
// Fix if the user swapped min and max
444+
if (led.minX_frac > led.maxX_frac)
445+
{
446+
std::swap(led.minX_frac, led.maxX_frac);
447+
}
448+
if (led.minY_frac > led.maxY_frac)
449+
{
450+
std::swap(led.minY_frac, led.maxY_frac);
451+
}
452+
453+
// Get the order of the rgb channels for this led (default is device order)
454+
led.colorOrder = stringToColorOrder(ledConfig.get("colorOrder", deviceOrderStr).asString());
455+
ledString.leds().push_back(led);
464456
}
465-
if (led.minY_frac > led.maxY_frac)
457+
}
458+
459+
// Make sure the leds are sorted (on their indices)
460+
std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; });
461+
return ledString;
462+
}
463+
464+
LedString Hyperion::createLedStringClone(const Json::Value& ledsConfig, const ColorOrder deviceOrder)
465+
{
466+
LedString ledString;
467+
const std::string deviceOrderStr = colorOrderToString(deviceOrder);
468+
int maxLedId = ledsConfig.size();
469+
for (const Json::Value& ledConfig : ledsConfig)
470+
{
471+
Led led;
472+
led.index = ledConfig["index"].asInt();
473+
led.clone = ledConfig.get("clone",-1).asInt();
474+
if ( led.clone < -1 || led.clone >= maxLedId )
466475
{
467-
std::swap(led.minY_frac, led.maxY_frac);
476+
Warning(Logger::getInstance("Core"), "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone);
477+
led.clone = -1;
468478
}
469479

470-
// Get the order of the rgb channels for this led (default is device order)
471-
const std::string ledOrderStr = ledConfig.get("colorOrder", deviceOrderStr).asString();
472-
led.colorOrder = stringToColorOrder(ledOrderStr);
480+
if ( led.clone >= 0 )
481+
{
482+
Debug(Logger::getInstance("Core"), "LED %d: clone from led %d", led.index, led.clone);
483+
led.minX_frac = 0;
484+
led.maxX_frac = 0;
485+
led.minY_frac = 0;
486+
led.maxY_frac = 0;
487+
// Get the order of the rgb channels for this led (default is device order)
488+
led.colorOrder = stringToColorOrder(ledConfig.get("colorOrder", deviceOrderStr).asString());
489+
490+
ledString.leds().push_back(led);
491+
}
473492

474-
ledString.leds().push_back(led);
475493
}
476494

477495
// Make sure the leds are sorted (on their indices)
478496
std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; });
479-
480497
return ledString;
481498
}
482499

@@ -543,6 +560,7 @@ MessageForwarder * Hyperion::getForwarder()
543560

544561
Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
545562
: _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"])))
563+
, _ledStringClone(createLedStringClone(jsonConfig["leds"], createColorOrder(jsonConfig["device"])))
546564
, _muxer(_ledString.leds().size())
547565
, _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"]))
548566
, _raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"]))
@@ -595,7 +613,7 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
595613
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
596614

597615
// create the effect engine
598-
_effectEngine = new EffectEngine(this, jsonConfig["effects"]);
616+
_effectEngine = new EffectEngine(this,jsonConfig["effects"]);
599617

600618
unsigned int hwLedCount = jsonConfig["device"].get("ledCount",getLedCount()).asUInt();
601619
_hwLedCount = std::max(hwLedCount, getLedCount());
@@ -867,14 +885,32 @@ void Hyperion::update()
867885
if (_adjustmentEnabled) _raw2ledAdjustment->applyAdjustment(_ledBuffer);
868886
if (_temperatureEnabled) _raw2ledTemperature->applyCorrection(_ledBuffer);
869887

870-
const std::vector<Led>& leds = _ledString.leds();
871-
888+
// init colororder vector, if nempty
889+
if (_ledStringColorOrder.empty())
890+
{
891+
for (Led& led : _ledString.leds())
892+
{
893+
_ledStringColorOrder.push_back(led.colorOrder);
894+
}
895+
for (Led& led : _ledStringClone.leds())
896+
{
897+
_ledStringColorOrder.insert(_ledStringColorOrder.begin() + led.index, led.colorOrder);
898+
}
899+
}
900+
901+
// insert cloned leds into buffer
902+
for (Led& led : _ledStringClone.leds())
903+
{
904+
_ledBuffer.insert(_ledBuffer.begin() + led.index, _ledBuffer.at(led.clone));
905+
}
906+
872907
int i = 0;
873908
for (ColorRgb& color : _ledBuffer)
874909
{
875-
const ColorOrder ledColorOrder = leds.at(i).colorOrder;
910+
//const ColorOrder ledColorOrder = leds.at(i).colorOrder;
911+
876912
// correct the color byte order
877-
switch (ledColorOrder)
913+
switch (_ledStringColorOrder.at(i))
878914
{
879915
case ORDER_RGB:
880916
// leave as it is

libsrc/hyperion/hyperion.schema.json

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"properties" :
1010
{
1111
"level" :
12-
{
12+
{
1313
"enum" : ["silent", "warn", "verbose", "debug"]
1414
}
1515
},
@@ -33,19 +33,19 @@
3333
},
3434
"output" :
3535
{
36-
"type" : "string",
37-
"required" : true
36+
"type" : "string"
3837
},
3938
"rate" :
4039
{
4140
"type" : "integer",
42-
"required" : false,
4341
"minimum" : 0
4442
},
4543
"colorOrder" :
4644
{
47-
"type" : "string",
48-
"required" : false
45+
"type":
46+
{
47+
"enum" : ["bgr", "rbg", "brg", "gbr", "grb"]
48+
}
4949
}
5050
},
5151
"additionalProperties" : true
@@ -852,20 +852,27 @@
852852
"type":"integer",
853853
"required":true
854854
},
855+
"clone":
856+
{
857+
"type":"integer"
858+
},
855859
"hscan":
856860
{
857861
"type":"object",
858-
"required":true,
859862
"properties":
860863
{
861864
"minimum":
862865
{
863866
"type":"number",
867+
"minimum" : 0,
868+
"maximum" : 1,
864869
"required":true
865870
},
866871
"maximum":
867872
{
868873
"type":"number",
874+
"minimum" : 0,
875+
"maximum" : 1,
869876
"required":true
870877
}
871878
},
@@ -874,26 +881,31 @@
874881
"vscan":
875882
{
876883
"type":"object",
877-
"required":true,
878884
"properties":
879885
{
880886
"minimum":
881887
{
882888
"type":"number",
889+
"minimum" : 0,
890+
"maximum" : 1,
883891
"required":true
884892
},
885893
"maximum":
886894
{
887895
"type":"number",
896+
"minimum" : 0,
897+
"maximum" : 1,
888898
"required":true
889899
}
890900
},
891901
"additionalProperties" : false
892902
},
893903
"colorOrder":
894904
{
895-
"type":"string",
896-
"required":false
905+
"type":
906+
{
907+
"enum" : ["bgr", "rbg", "brg", "gbr", "grb"]
908+
}
897909
}
898910
},
899911
"additionalProperties" : false

0 commit comments

Comments
 (0)