Fix some more threading errors (#911)

This commit is contained in:
Murat Seker
2020-08-02 10:44:42 +02:00
committed by GitHub
parent d9e33885a0
commit 8824e69986
9 changed files with 132 additions and 156 deletions

View File

@@ -15,15 +15,12 @@
#include <QTimer>
// hyperion includes
#include <leddevice/LedDeviceWrapper.h>
#include <hyperion/GrabberWrapper.h>
#include <utils/jsonschema/QJsonFactory.h>
#include <utils/jsonschema/QJsonSchemaChecker.h>
#include <HyperionConfig.h>
#include <utils/SysInfo.h>
#include <utils/ColorSys.h>
#include <utils/Process.h>
//#include <utils/ApiSync.h>
// bonjour wrapper
#include <bonjour/bonjourbrowserwrapper.h>
@@ -95,7 +92,6 @@ void API::setColor(const int &priority, const std::vector<uint8_t> &ledColors, c
fledColors.emplace_back(ColorRgb{ledColors[i], ledColors[i + 1], ledColors[i + 2]});
}
QMetaObject::invokeMethod(_hyperion, "setColor", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(std::vector<ColorRgb>, fledColors), Q_ARG(int, timeout_ms), Q_ARG(QString, origin));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setColor", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, priority), Q_ARG(std::vector<ColorRgb>, fledColors), Q_ARG(int, timeout_ms), Q_ARG(QString, origin), Q_ARG(hyperion::Components, callerComp));
}
}
@@ -175,9 +171,6 @@ bool API::setImage(ImageCmdData &data, hyperion::Components comp, QString &reply
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(hyperion::Components, comp), Q_ARG(QString, data.origin), Q_ARG(QString, data.imgName));
QMetaObject::invokeMethod(_hyperion, "setInputImage", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(Image<ColorRgb>, image), Q_ARG(int64_t, data.duration));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "registerInput", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, data.priority), Q_ARG(hyperion::Components, comp), Q_ARG(QString, data.origin), Q_ARG(QString, data.imgName), Q_ARG(hyperion::Components, callerComp));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setInputImage", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, data.priority), Q_ARG(Image<ColorRgb>, image), Q_ARG(int64_t, data.duration), Q_ARG(hyperion::Components, comp), Q_ARG(hyperion::Components, callerComp));
return true;
}
@@ -186,7 +179,6 @@ bool API::clearPriority(const int &priority, QString &replyMsg, const hyperion::
if (priority < 0 || (priority > 0 && priority < 254))
{
QMetaObject::invokeMethod(_hyperion, "clear", Qt::QueuedConnection, Q_ARG(int, priority));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "clearPriority", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, priority), Q_ARG(hyperion::Components, callerComp));
}
else
{
@@ -203,7 +195,6 @@ bool API::setComponentState(const QString &comp, bool &compState, QString &reply
if (component != COMP_INVALID)
{
QMetaObject::invokeMethod(_hyperion, "compStateChangeRequest", Qt::QueuedConnection, Q_ARG(hyperion::Components, component), Q_ARG(bool, compState));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "compStateChangeRequest", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(hyperion::Components, component), Q_ARG(bool, compState), Q_ARG(hyperion::Components, callerComp));
return true;
}
replyMsg = QString("Unknown component name: %1").arg(comp);
@@ -213,13 +204,11 @@ bool API::setComponentState(const QString &comp, bool &compState, QString &reply
void API::setLedMappingType(const int &type, const hyperion::Components &callerComp)
{
QMetaObject::invokeMethod(_hyperion, "setLedMappingType", Qt::QueuedConnection, Q_ARG(int, type));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setLedMappingType", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, type), Q_ARG(hyperion::Components, callerComp));
}
void API::setVideoMode(const VideoMode &mode, const hyperion::Components &callerComp)
{
QMetaObject::invokeMethod(_hyperion, "setVideoMode", Qt::QueuedConnection, Q_ARG(VideoMode, mode));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setVideoMode", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(VideoMode, mode), Q_ARG(hyperion::Components, callerComp));
}
void API::setEffect(const EffectCmdData &dat, const hyperion::Components &callerComp)
@@ -231,20 +220,17 @@ void API::setEffect(const EffectCmdData &dat, const hyperion::Components &caller
else
{
QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::QueuedConnection, Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setEffect", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin), Q_ARG(hyperion::Components, callerComp));
}
}
void API::setSourceAutoSelect(const bool state, const hyperion::Components &callerComp)
{
QMetaObject::invokeMethod(_hyperion, "setSourceAutoSelect", Qt::QueuedConnection, Q_ARG(bool, state));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setSourceAutoSelect", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(bool, state), Q_ARG(hyperion::Components, callerComp));
}
void API::setVisiblePriority(const int &priority, const hyperion::Components &callerComp)
{
QMetaObject::invokeMethod(_hyperion, "setVisiblePriority", Qt::QueuedConnection, Q_ARG(int, priority));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "setVisiblePriority", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, priority), Q_ARG(hyperion::Components, callerComp));
}
void API::registerInput(const int &priority, const hyperion::Components &component, const QString &origin, const QString &owner, const hyperion::Components &callerComp)
@@ -255,7 +241,6 @@ void API::registerInput(const int &priority, const hyperion::Components &compone
_activeRegisters.insert({priority, registerData{component, origin, owner, callerComp}});
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(hyperion::Components, component), Q_ARG(QString, origin), Q_ARG(QString, owner));
//QMetaObject::invokeMethod(ApiSync::getInstance(), "registerInput", Qt::QueuedConnection, Q_ARG(QObject *, _hyperion), Q_ARG(int, priority), Q_ARG(hyperion::Components, component), Q_ARG(QString, origin), Q_ARG(QString, owner), Q_ARG(hyperion::Components, callerComp));
}
void API::unregisterInput(const int &priority)

View File

@@ -626,8 +626,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
// ACTIVE EFFECT INFO
QJsonArray activeEffects;
const std::list<ActiveEffectDefinition> &activeEffectsDefinitions = _hyperion->getActiveEffects();
for (const ActiveEffectDefinition &activeEffectDefinition : activeEffectsDefinitions)
for (const ActiveEffectDefinition &activeEffectDefinition : _hyperion->getActiveEffects())
{
if (activeEffectDefinition.priority != PriorityMuxer::LOWEST_PRIORITY - 1)
{
@@ -1236,7 +1235,9 @@ void JsonAPI::handleAuthorizeCommand(const QJsonObject &message, const QString &
sendSuccessDataReply(QJsonDocument(arr), command + "-" + subc, tan);
}
else
{
sendErrorReply("No Authorization", command + "-" + subc, tan);
}
return;
}
@@ -1411,60 +1412,43 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString &
}
else
*/ {
QJsonObject config;
config.insert("type", devType);
LedDevice* ledDevice = nullptr;
if (subc == "discover")
{
QJsonObject config;
config.insert("type", devType);
// Pointer of current led device
LedDevice* _ledDevice;
_ledDevice = LedDeviceFactory::construct(config);
QJsonObject devicesDiscovered = _ledDevice->discover();
ledDevice = LedDeviceFactory::construct(config);
const QJsonObject devicesDiscovered = ledDevice->discover();
Debug(_log, "response: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() );
sendSuccessDataReply(QJsonDocument(devicesDiscovered), full_command, tan);
delete _ledDevice;
sendSuccessDataReply(QJsonDocument(devicesDiscovered), full_command, tan);
}
else if (subc == "getProperties")
{
ledDevice = LedDeviceFactory::construct(config);
const QJsonObject &params = message["params"].toObject();
QJsonObject config;
config.insert("type", devType);
// Pointer of current led device
LedDevice* _ledDevice;
_ledDevice = LedDeviceFactory::construct(config);
QJsonObject deviceProperties = _ledDevice->getProperties(params);
const QJsonObject deviceProperties = ledDevice->getProperties(params);
Debug(_log, "response: [%s]", QString(QJsonDocument(deviceProperties).toJson(QJsonDocument::Compact)).toUtf8().constData() );
sendSuccessDataReply(QJsonDocument(deviceProperties), full_command, tan);
delete _ledDevice;
sendSuccessDataReply(QJsonDocument(deviceProperties), full_command, tan);
}
else if (subc == "identify")
{
ledDevice = LedDeviceFactory::construct(config);
const QJsonObject &params = message["params"].toObject();
QJsonObject config;
config.insert("type", devType);
// Pointer of current led device
LedDevice* _ledDevice;
_ledDevice = LedDeviceFactory::construct(config);
_ledDevice->identify(params);
ledDevice->identify(params);
sendSuccessReply(full_command, tan);
delete _ledDevice;
}
else
{
sendErrorReply("Unknown or missing subcommand", full_command, tan);
}
delete ledDevice;
}
}

View File

@@ -148,13 +148,16 @@ bool JsonCB::subscribeFor(const QString& type, const bool & unsubscribe)
return true;
}
void JsonCB::resetSubscriptions(void){
for(const auto & entry : getSubscribedCommands()){
void JsonCB::resetSubscriptions()
{
for(const auto & entry : getSubscribedCommands())
{
subscribeFor(entry, true);
}
}
void JsonCB::setSubscriptionsTo(Hyperion* hyperion){
void JsonCB::setSubscriptionsTo(Hyperion* hyperion)
{
// get current subs
QStringList currSubs(getSubscribedCommands());

View File

@@ -16,6 +16,7 @@
// utils
#include <utils/hyperion.h>
#include <utils/GlobalSignals.h>
#include <utils/Logger.h>
// Leddevice includes
#include <leddevice/LedDeviceWrapper.h>
@@ -80,7 +81,7 @@ void Hyperion::start()
_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount());
// init colororder vector
for (Led& led : _ledString.leds())
for (const Led& led : _ledString.leds())
{
_ledStringColorOrder.push_back(led.colorOrder);
}
@@ -190,8 +191,6 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
}
else if(type == settings::LEDS)
{
QMutexLocker lock(&_changes);
const QJsonArray leds = config.array();
// stop and cache all running effects, as effects depend heavily on ledlayout
@@ -207,7 +206,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
_ledBuffer = color;
_ledStringColorOrder.clear();
for (Led& led : _ledString.leds())
for (const Led& led : _ledString.leds())
{
_ledStringColorOrder.push_back(led.colorOrder);
}
@@ -224,7 +223,6 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
}
else if(type == settings::DEVICE)
{
QMutexLocker lock(&_changes);
QJsonObject dev = config.object();
// handle hwLedCount update
@@ -237,7 +235,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
_imageProcessor->setLedString(_ledString);
_ledStringColorOrder.clear();
for (Led& led : _ledString.leds())
for (const Led& led : _ledString.leds())
{
_ledStringColorOrder.push_back(led.colorOrder);
}
@@ -258,7 +256,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
update();
}
QJsonDocument Hyperion::getSetting(const settings::type& type)
QJsonDocument Hyperion::getSetting(const settings::type& type) const
{
return _settingsManager->getSetting(type);
}
@@ -270,7 +268,7 @@ bool Hyperion::saveSettings(QJsonObject config, const bool& correct)
int Hyperion::getLatchTime() const
{
return _ledDeviceWrapper->getLatchTime();
return _ledDeviceWrapper->getLatchTime();
}
unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz, unsigned updateDelay)
@@ -308,7 +306,7 @@ void Hyperion::setNewComponentState(const hyperion::Components& component, const
_componentRegister.setNewComponentState(component, state);
}
std::map<hyperion::Components, bool> Hyperion::getAllComponents()
std::map<hyperion::Components, bool> Hyperion::getAllComponents() const
{
return _componentRegister.getRegister();
}
@@ -409,7 +407,7 @@ const QStringList & Hyperion::getAdjustmentIds() const
return _raw2ledAdjustment->getAdjustmentIds();
}
ColorAdjustment * Hyperion::getAdjustment(const QString& id)
ColorAdjustment * Hyperion::getAdjustment(const QString& id) const
{
return _raw2ledAdjustment->getAdjustment(id);
}
@@ -457,7 +455,7 @@ QList<int> Hyperion::getActivePriorities() const
return _muxer.getPriorities();
}
const Hyperion::InputInfo Hyperion::getPriorityInfo(const int priority) const
Hyperion::InputInfo Hyperion::getPriorityInfo(const int priority) const
{
return _muxer.getInputInfo(priority);
}
@@ -477,17 +475,17 @@ const std::list<EffectDefinition> & Hyperion::getEffects() const
return _effectEngine->getEffects();
}
const std::list<ActiveEffectDefinition> & Hyperion::getActiveEffects()
const std::list<ActiveEffectDefinition> & Hyperion::getActiveEffects() const
{
return _effectEngine->getActiveEffects();
}
const std::list<EffectSchema> & Hyperion::getEffectSchemas()
const std::list<EffectSchema> & Hyperion::getEffectSchemas() const
{
return _effectEngine->getEffectSchemas();
}
const QJsonObject& Hyperion::getQJsonConfig()
const QJsonObject& Hyperion::getQJsonConfig() const
{
return _settingsManager->getSettings();
}
@@ -511,7 +509,7 @@ void Hyperion::setLedMappingType(const int& mappingType)
}
}
const int & Hyperion::getLedMappingType()
int Hyperion::getLedMappingType() const
{
return _imageProcessor->getUserLedMappingType();
}
@@ -521,12 +519,12 @@ void Hyperion::setVideoMode(const VideoMode& mode)
emit videoMode(mode);
}
const VideoMode & Hyperion::getCurrentVideoMode()
VideoMode Hyperion::getCurrentVideoMode() const
{
return _currVideoMode;
}
const QString & Hyperion::getActiveDeviceType()
QString Hyperion::getActiveDeviceType() const
{
return _ledDeviceWrapper->getActiveDeviceType();
}
@@ -540,8 +538,6 @@ void Hyperion::handleVisibleComponentChanged(const hyperion::Components &comp)
void Hyperion::update()
{
QMutexLocker lock(&_changes);
// Obtain the current priority channel
int priority = _muxer.getCurrentPriority();
const PriorityMuxer::InputInfo priorityInfo = _muxer.getInputInfo(priority);
@@ -554,7 +550,9 @@ void Hyperion::update()
_ledBuffer = _imageProcessor->process(image);
}
else
{
_ledBuffer = priorityInfo.ledColors;
}
// emit rawLedColors before transform
emit rawLedColors(_ledBuffer);

View File

@@ -11,10 +11,12 @@
#include <utils/JsonUtils.h>
// qt
#include <QMutexLocker>
#include <QThread>
#include <QDir>
LedDeviceRegistry LedDeviceWrapper::_ledDeviceMap = LedDeviceRegistry();
LedDeviceRegistry LedDeviceWrapper::_ledDeviceMap {};
QMutex LedDeviceWrapper::_ledDeviceMapLock {QMutex::Recursive};
LedDeviceWrapper::LedDeviceWrapper(Hyperion* hyperion)
: QObject(hyperion)
@@ -47,18 +49,16 @@ void LedDeviceWrapper::createLedDevice(const QJsonObject& config)
// create thread and device
QThread* thread = new QThread(this);
thread->setObjectName("LedDeviceWrapperThread");
thread->setObjectName("LedDeviceThread");
_ledDevice = LedDeviceFactory::construct(config);
_ledDevice->moveToThread(thread);
// setup thread management
connect(thread, &QThread::started, _ledDevice, &LedDevice::start);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
connect(thread, &QThread::finished, _ledDevice, &LedDevice::deleteLater);
// further signals
connect(this, &LedDeviceWrapper::updateLeds, _ledDevice, &LedDevice::updateLeds, Qt::QueuedConnection);
connect(this, &LedDeviceWrapper::setEnable, _ledDevice, &LedDevice::setEnable);
connect(this, &LedDeviceWrapper::closeLedDevice, _ledDevice, &LedDevice::stop, Qt::BlockingQueuedConnection);
connect(_ledDevice, &LedDevice::enableStateChanged, this, &LedDeviceWrapper::handleInternalEnableState, Qt::QueuedConnection);
@@ -73,11 +73,10 @@ const QJsonObject LedDeviceWrapper::getLedDeviceSchemas()
Q_INIT_RESOURCE(LedDeviceSchemas);
// read the JSON schema from the resource
QDir d(":/leddevices/");
QStringList l = d.entryList();
QDir dir(":/leddevices/");
QJsonObject result, schemaJson;
for(QString &item : l)
for(QString &item : dir.entryList())
{
QString schemaPath(QString(":/leddevices/")+item);
QString devName = item.remove("schema-");
@@ -105,33 +104,46 @@ const QJsonObject LedDeviceWrapper::getLedDeviceSchemas()
int LedDeviceWrapper::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr)
{
QMutexLocker lock(&_ledDeviceMapLock);
_ledDeviceMap.emplace(name,funcPtr);
return 0;
}
const LedDeviceRegistry& LedDeviceWrapper::getDeviceMap()
{
QMutexLocker lock(&_ledDeviceMapLock);
return _ledDeviceMap;
}
int LedDeviceWrapper::getLatchTime()
{
return _ledDevice->getLatchTime();
int value = 0;
QMetaObject::invokeMethod(_ledDevice, "getLatchTime", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, value));
return value;
}
const QString & LedDeviceWrapper::getActiveDeviceType()
QString LedDeviceWrapper::getActiveDeviceType()
{
return _ledDevice->getActiveDeviceType();
QString value = 0;
QMetaObject::invokeMethod(_ledDevice, "getActiveDeviceType", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, value));
return value;
}
const QString & LedDeviceWrapper::getColorOrder()
QString LedDeviceWrapper::getColorOrder()
{
return _ledDevice->getColorOrder();
QString value;
QMetaObject::invokeMethod(_ledDevice, "getColorOrder", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, value));
return value;
}
unsigned int LedDeviceWrapper::getLedCount() const
{
return _ledDevice->getLedCount();
unsigned int value = 0;
QMetaObject::invokeMethod(_ledDevice, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned int, value));
return value;
}
bool LedDeviceWrapper::enabled()
@@ -146,7 +158,8 @@ void LedDeviceWrapper::handleComponentState(const hyperion::Components component
emit setEnable(state);
//Get device's state, considering situations where it is not ready
bool deviceState = _ledDevice->componentState();
bool deviceState = false;
QMetaObject::invokeMethod(_ledDevice, "componentState", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, deviceState));
_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, deviceState);
_enabled = deviceState;
}
@@ -162,7 +175,7 @@ void LedDeviceWrapper::stopDeviceThread()
{
// turns the LEDs off & stop refresh timers
emit closeLedDevice();
std::cout << "[hyperiond LedDeviceWrapper] <INFO> LedDevice \'" << QSTRING_CSTR(_ledDevice->getActiveDeviceType()) << "\' closed" << std::endl;
std::cout << "[hyperiond LedDeviceWrapper] <INFO> LedDevice \'" << QSTRING_CSTR(getActiveDeviceType()) << "\' closed" << std::endl;
// get current thread
QThread* oldThread = _ledDevice->thread();