refactor: Led layout, clearAll (#703)

* add SSDP name field

* YALL - yet another led layout

* led layout migration

* add initial vscode config

* merge clearAll with clear, rename Hyperion::compStateChange

* simpler components api

* Corrected code formatting

+ triggered PR build

* fix: regression from #636

* Support for color patterns

Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
This commit is contained in:
brindosch
2020-02-26 18:54:56 +01:00
committed by GitHub
parent ef51d28463
commit 8db85c9a5a
47 changed files with 656 additions and 738 deletions

View File

@@ -25,7 +25,7 @@ CaptureCont::CaptureCont(Hyperion* hyperion)
connect(_hyperion, &Hyperion::settingsChanged, this, &CaptureCont::handleSettingsUpdate);
// comp changes
connect(_hyperion, &Hyperion::componentStateChanged, this, &CaptureCont::componentStateChanged);
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &CaptureCont::handleCompStateChangeRequest);
// inactive timer system
connect(_systemInactiveTimer, &QTimer::timeout, this, &CaptureCont::setSystemInactive);
@@ -85,8 +85,8 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable)
_systemCaptName = "";
}
_systemCaptEnabled = enable;
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_GRABBER, enable);
_hyperion->setComponentState(hyperion::COMP_GRABBER, enable);
_hyperion->setNewComponentState(hyperion::COMP_GRABBER, enable);
//emit _hyperion->compStateChangeRequest(hyperion::COMP_GRABBER, enable);
}
}
@@ -108,8 +108,8 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable)
_v4lCaptName = "";
}
_v4lCaptEnabled = enable;
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_V4L, enable);
_hyperion->setComponentState(hyperion::COMP_V4L, enable);
_hyperion->setNewComponentState(hyperion::COMP_V4L, enable);
//emit _hyperion->compStateChangeRequest(hyperion::COMP_V4L, enable);
}
}
@@ -134,7 +134,7 @@ void CaptureCont::handleSettingsUpdate(const settings::type& type, const QJsonDo
}
}
void CaptureCont::componentStateChanged(const hyperion::Components component, bool enable)
void CaptureCont::handleCompStateChangeRequest(const hyperion::Components component, bool enable)
{
if(component == hyperion::COMP_GRABBER)
{

View File

@@ -16,51 +16,20 @@ ComponentRegister::ComponentRegister(Hyperion* hyperion)
{
_componentStates.emplace(e, ((e == COMP_ALL) ? true : false));
}
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &ComponentRegister::handleCompStateChangeRequest);
}
ComponentRegister::~ComponentRegister()
{
}
bool ComponentRegister::setHyperionEnable(const bool& state)
{
if(!state && _prevComponentStates.empty())
{
Debug(_log,"Disable Hyperion, store current component states");
for(const auto comp : _componentStates)
{
// save state
_prevComponentStates.emplace(comp.first, comp.second);
// disable if enabled
if(comp.second)
_hyperion->setComponentState(comp.first, false);
}
componentStateChanged(COMP_ALL, false);
return true;
}
else if(state && !_prevComponentStates.empty())
{
Debug(_log,"Enable Hyperion, recover previous component states");
for(const auto comp : _prevComponentStates)
{
// if comp was enabled, enable again
if(comp.second)
_hyperion->setComponentState(comp.first, true);
}
_prevComponentStates.clear();
componentStateChanged(COMP_ALL, true);
return true;
}
return false;
}
int ComponentRegister::isComponentEnabled(const hyperion::Components& comp) const
{
return (_componentStates.count(comp)) ? _componentStates.at(comp) : -1;
}
void ComponentRegister::componentStateChanged(const hyperion::Components comp, const bool activated)
void ComponentRegister::setNewComponentState(const hyperion::Components comp, const bool activated)
{
if(_componentStates[comp] != activated)
{
@@ -70,3 +39,38 @@ void ComponentRegister::componentStateChanged(const hyperion::Components comp, c
emit updatedComponentState(comp, activated);
}
}
void ComponentRegister::handleCompStateChangeRequest(const hyperion::Components comp, const bool activated)
{
if(comp == COMP_ALL && !_inProgress)
{
_inProgress = true;
if(!activated && _prevComponentStates.empty())
{
Debug(_log,"Disable Hyperion, store current component states");
for(const auto comp : _componentStates)
{
// save state
_prevComponentStates.emplace(comp.first, comp.second);
// disable if enabled
if(comp.second)
emit _hyperion->compStateChangeRequest(comp.first, false);
}
setNewComponentState(COMP_ALL, false);
}
else if(activated && !_prevComponentStates.empty())
{
Debug(_log,"Enable Hyperion, recover previous component states");
for(const auto comp : _prevComponentStates)
{
// if comp was enabled, enable again
if(comp.second)
emit _hyperion->compStateChangeRequest(comp.first, true);
}
_prevComponentStates.clear();
setNewComponentState(COMP_ALL, true);
}
_inProgress = false;
}
}

View File

@@ -104,7 +104,7 @@ void Hyperion::start()
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
_ledDeviceWrapper = new LedDeviceWrapper(this);
connect(this, &Hyperion::componentStateChanged, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
connect(this, &Hyperion::compStateChangeRequest, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
connect(this, &Hyperion::ledDeviceData, _ledDeviceWrapper, &LedDeviceWrapper::updateLeds);
_ledDeviceWrapper->createLedDevice(ledDevice);
@@ -132,7 +132,6 @@ void Hyperion::start()
// forwards global signals to the corresponding slots
connect(GlobalSignals::getInstance(), &GlobalSignals::registerGlobalInput, this, &Hyperion::registerInput);
connect(GlobalSignals::getInstance(), &GlobalSignals::clearGlobalInput, this, &Hyperion::clear);
connect(GlobalSignals::getInstance(), &GlobalSignals::clearAllGlobalInput, this, &Hyperion::clearall);
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor, this, &Hyperion::setColor);
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage, this, &Hyperion::setInputImage);
@@ -157,7 +156,7 @@ void Hyperion::stop()
void Hyperion::freeObjects(bool emitCloseSignal)
{
// switch off all leds
clearall(true);
clear(-1,true);
if (emitCloseSignal)
{
@@ -309,13 +308,17 @@ bool Hyperion::sourceAutoSelectEnabled()
void Hyperion::setNewComponentState(const hyperion::Components& component, const bool& state)
{
_componentRegister.componentStateChanged(component, state);
_componentRegister.setNewComponentState(component, state);
}
void Hyperion::setComponentState(const hyperion::Components component, const bool state)
std::map<hyperion::Components, bool> Hyperion::getAllComponents()
{
// TODO REMOVE THIS STEP
emit componentStateChanged(component, state);
return _componentRegister.getRegister();
}
int Hyperion::isComponentEnabled(const hyperion::Components &comp)
{
return _componentRegister.isComponentEnabled(comp);
}
void Hyperion::registerInput(const int priority, const hyperion::Components& component, const QString& origin, const QString& owner, unsigned smooth_cfg)
@@ -372,14 +375,25 @@ bool Hyperion::setInputInactive(const quint8& priority)
return _muxer.setInputInactive(priority);
}
void Hyperion::setColor(const int priority, const ColorRgb &color, const int timeout_ms, const QString& origin, bool clearEffects)
void Hyperion::setColor(const int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms, const QString &origin, bool clearEffects)
{
// clear effect if this call does not come from an effect
if(clearEffects)
if (clearEffects)
_effectEngine->channelCleared(priority);
// create led vector from single color
std::vector<ColorRgb> ledColors(_ledString.leds().size(), color);
// create full led vector from single/multiple colors
unsigned int size = _ledString.leds().size();
std::vector<ColorRgb> newLedColors;
while (true)
{
for (const auto &entry : ledColors)
{
newLedColors.emplace_back(entry);
if (newLedColors.size() == size)
goto end;
}
}
end:
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
clear(priority);
@@ -388,8 +402,8 @@ void Hyperion::setColor(const int priority, const ColorRgb &color, const int tim
registerInput(priority, hyperion::COMP_COLOR, origin);
// write color to muxer & queuePush
setInput(priority, ledColors, timeout_ms);
if(timeout_ms <= 0)
setInput(priority, newLedColors, timeout_ms);
if (timeout_ms <= 0)
_muxer.queuePush();
}
@@ -409,26 +423,28 @@ void Hyperion::adjustmentsUpdated()
update();
}
bool Hyperion::clear(const int priority)
bool Hyperion::clear(const int priority, bool forceClearAll)
{
// send clear signal to the effect engine
// (outside the check so the effect gets cleared even when the effect is not sending colors)
_effectEngine->channelCleared(priority);
if (priority < 0)
{
_muxer.clearAll(forceClearAll);
if(_muxer.clearInput(priority))
// send clearall signal to the effect engine
_effectEngine->allChannelsCleared();
return true;
}
else
{
// send clear signal to the effect engine
// (outside the check so the effect gets cleared even when the effect is not sending colors)
_effectEngine->channelCleared(priority);
if (_muxer.clearInput(priority))
return true;
}
return false;
}
void Hyperion::clearall(bool forceClearAll)
{
_muxer.clearAll(forceClearAll);
// send clearall signal to the effect engine
_effectEngine->allChannelsCleared();
}
int Hyperion::getCurrentPriority() const
{
return _muxer.getCurrentPriority();

View File

@@ -76,7 +76,7 @@ bool HyperionIManager::startInstance(const quint8& inst, const bool& block)
// from Hyperion
connect(hyperion, &Hyperion::settingsChanged, this, &HyperionIManager::settingsChanged);
connect(hyperion, &Hyperion::videoMode, this, &HyperionIManager::requestVideoMode);
connect(hyperion, &Hyperion::componentStateChanged, this, &HyperionIManager::componentStateChanged);
connect(hyperion, &Hyperion::compStateChangeRequest, this, &HyperionIManager::compStateChangeRequest);
// to Hyperion
connect(this, &HyperionIManager::newVideoMode, hyperion, &Hyperion::newVideoMode);

View File

@@ -38,7 +38,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument& config, Hyperion
_cfgList.append(cfg);
// listen for comp changes
connect(_hyperion, &Hyperion::componentStateChanged, this, &LinearColorSmoothing::componentStateChange);
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &LinearColorSmoothing::componentStateChange);
// timer
connect(_timer, &QTimer::timeout, this, &LinearColorSmoothing::updateLeds);
}
@@ -235,7 +235,7 @@ void LinearColorSmoothing::setEnable(bool enable)
clearQueuedColors();
}
// update comp register
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_SMOOTHING, enable);
_hyperion->setNewComponentState(hyperion::COMP_SMOOTHING, enable);
}
void LinearColorSmoothing::setPause(bool pause)

View File

@@ -28,7 +28,7 @@ MessageForwarder::MessageForwarder(Hyperion *hyperion)
connect(_hyperion, &Hyperion::settingsChanged, this, &MessageForwarder::handleSettingsUpdate);
// component changes
connect(_hyperion, &Hyperion::componentStateChanged, this, &MessageForwarder::componentStateChanged);
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &MessageForwarder::handleCompStateChangeRequest);
// connect with Muxer visible priority changes
connect(_muxer, &PriorityMuxer::visiblePriorityChanged, this, &MessageForwarder::handlePriorityChanges);
@@ -91,18 +91,18 @@ void MessageForwarder::handleSettingsUpdate(const settings::type &type, const QJ
}
// update comp state
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_FORWARDER, obj["enable"].toBool(true));
_hyperion->setNewComponentState(hyperion::COMP_FORWARDER, obj["enable"].toBool(true));
}
}
void MessageForwarder::componentStateChanged(const hyperion::Components component, bool enable)
void MessageForwarder::handleCompStateChangeRequest(const hyperion::Components component, bool enable)
{
if (component == hyperion::COMP_FORWARDER && _forwarder_enabled != enable)
{
_forwarder_enabled = enable;
handleSettingsUpdate(settings::NETFORWARD, _hyperion->getSetting(settings::NETFORWARD));
Info(_log, "Forwarder change state to %s", (_forwarder_enabled ? "enabled" : "disabled"));
_hyperion->getComponentRegister().componentStateChanged(component, _forwarder_enabled);
_hyperion->setNewComponentState(component, _forwarder_enabled);
}
}

View File

@@ -74,6 +74,13 @@ SettingsManager::SettingsManager(const quint8& instance, QObject* parent)
dbConfig[key] = doc.object();
}
// possible data upgrade steps to prevent data loss
if(handleConfigUpgrade(dbConfig))
{
saveSettings(dbConfig, true);
}
// validate full dbconfig against schema, on error we need to rewrite entire table
QJsonSchemaChecker schemaChecker;
schemaChecker.setSchema(schemaJson);
@@ -108,6 +115,9 @@ const QJsonDocument SettingsManager::getSetting(const settings::type& type)
bool SettingsManager::saveSettings(QJsonObject config, const bool& correct)
{
// optional data upgrades e.g. imported legacy/older configs
// handleConfigUpgrade(config);
// we need to validate data against schema
QJsonSchemaChecker schemaChecker;
schemaChecker.setSchema(schemaJson);
@@ -156,3 +166,66 @@ bool SettingsManager::saveSettings(QJsonObject config, const bool& correct)
}
return true;
}
bool SettingsManager::handleConfigUpgrade(QJsonObject& config)
{
bool migrated = false;
// LED LAYOUT UPGRADE
// from { hscan: { minimum: 0.2, maximum: 0.3 }, vscan: { minimum: 0.2, maximumn: 0.3 } }
// from { h: { min: 0.2, max: 0.3 }, v: { min: 0.2, max: 0.3 } }
// to { hmin: 0.2, hmax: 0.3, vmin: 0.2, vmax: 0.3}
if(config.contains("leds"))
{
const QJsonArray ledarr = config["leds"].toArray();
const QJsonObject led = ledarr[0].toObject();
if(led.contains("hscan") || led.contains("h"))
{
const bool whscan = led.contains("hscan");
QJsonArray newLedarr;
for(const auto & entry : ledarr)
{
const QJsonObject led = entry.toObject();
QJsonObject hscan;
QJsonObject vscan;
QJsonValue hmin;
QJsonValue hmax;
QJsonValue vmin;
QJsonValue vmax;
QJsonObject nL;
if(whscan)
{
hscan = led["hscan"].toObject();
vscan = led["vscan"].toObject();
hmin = hscan["minimum"];
hmax = hscan["maximum"];
vmin = vscan["minimum"];
vmax = vscan["maximum"];
}
else
{
hscan = led["h"].toObject();
vscan = led["v"].toObject();
hmin = hscan["min"];
hmax = hscan["max"];
vmin = vscan["min"];
vmax = vscan["max"];
}
// append to led object
nL["hmin"] = hmin;
nL["hmax"] = hmax;
nL["vmin"] = vmin;
nL["vmax"] = vmax;
newLedarr.append(nL);
}
// replace
config["leds"] = newLedarr;
migrated = true;
Debug(_log,"LED Layout migrated");
}
}
return migrated;
}

View File

@@ -1,72 +1,64 @@
{
"type":"array",
"required":true,
"minItems":1,
"items":
{
"type":"object",
"required" : true,
"properties":
{
"h":
{
"type":"object",
"required" : true,
"properties":
{
"min":
{
"type":"number",
"minimum" : 0,
"maximum" : 1,
"required":true,
"default" : 0
},
"max":
{
"type":"number",
"minimum" : 0,
"maximum" : 1,
"required":true,
"default" : 0.1
}
},
"additionalProperties" : false
"type": "array",
"required": true,
"minItems": 1,
"items": {
"type": "object",
"required": true,
"properties": {
"hmin": {
"type": "number",
"minimum": 0,
"maximum": 1,
"required": true,
"default": 0
},
"v":
{
"type":"object",
"required" : true,
"properties":
{
"min":
{
"type":"number",
"minimum" : 0,
"maximum" : 1,
"required":true,
"default" : 0
},
"max":
{
"type":"number",
"minimum" : 0,
"maximum" : 1,
"required":true,
"default" : 0.1
}
},
"additionalProperties" : false
"hmax": {
"type": "number",
"minimum": 0,
"maximum": 1,
"required": true,
"default": 0.1
},
"colorOrder":
{
"vmin": {
"type": "number",
"minimum": 0,
"maximum": 1,
"required": true,
"default": 0
},
"vmax": {
"type": "number",
"minimum": 0,
"maximum": 1,
"required": true,
"default": 0.1
},
"colorOrder": {
"type": "string",
"enum" : ["rgb", "bgr", "rbg", "brg", "gbr", "grb"],
"options" : {
"enum_titles" : ["edt_conf_enum_rgb", "edt_conf_enum_bgr", "edt_conf_enum_rbg", "edt_conf_enum_brg", "edt_conf_enum_gbr", "edt_conf_enum_grb"]
"enum": [
"rgb",
"bgr",
"rbg",
"brg",
"gbr",
"grb"
],
"options": {
"enum_titles": [
"edt_conf_enum_rgb",
"edt_conf_enum_bgr",
"edt_conf_enum_rbg",
"edt_conf_enum_brg",
"edt_conf_enum_gbr",
"edt_conf_enum_grb"
]
}
},
"name": {
"type": "string"
}
},
"additionalProperties" : false
"additionalProperties": false
}
}
}