mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
460 lines
13 KiB
C++
460 lines
13 KiB
C++
#include <api/JsonCallbacks.h>
|
|
#include <api/JsonInfo.h>
|
|
#include <api/JsonApiSubscription.h>
|
|
|
|
#include <hyperion/Hyperion.h>
|
|
#include <hyperion/HyperionIManager.h>
|
|
#include <events/EventHandler.h>
|
|
#include <hyperion/ComponentRegister.h>
|
|
#include <hyperion/PriorityMuxer.h>
|
|
#include <utils/ColorSys.h>
|
|
#include <hyperion/ImageProcessor.h>
|
|
|
|
#include <QDateTime>
|
|
#include <QVariant>
|
|
#include <QImage>
|
|
#include <QBuffer>
|
|
|
|
using namespace hyperion;
|
|
|
|
JsonCallbacks::JsonCallbacks(Logger *log, const QString& peerAddress, QObject* parent)
|
|
: QObject(parent)
|
|
, _log (log)
|
|
, _hyperion(nullptr)
|
|
, _peerAddress (peerAddress)
|
|
, _componentRegister(nullptr)
|
|
, _prioMuxer(nullptr)
|
|
, _islogMsgStreamingActive(false)
|
|
{
|
|
qRegisterMetaType<PriorityMuxer::InputsMap>("InputsMap");
|
|
}
|
|
|
|
bool JsonCallbacks::subscribe(const Subscription::Type cmd)
|
|
{
|
|
switch (cmd) {
|
|
case Subscription::AdjustmentUpdate:
|
|
connect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCallbacks::handleAdjustmentChange);
|
|
break;
|
|
case Subscription::ComponentsUpdate:
|
|
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCallbacks::handleComponentState);
|
|
break;
|
|
#if defined(ENABLE_EFFECTENGINE)
|
|
case Subscription::EffectsUpdate:
|
|
connect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCallbacks::handleEffectListChange);
|
|
break;
|
|
#endif
|
|
case Subscription::EventUpdate:
|
|
connect(EventHandler::getInstance().data(), &EventHandler::signalEvent, this, &JsonCallbacks::handleEventUpdate);
|
|
break;
|
|
case Subscription::ImageToLedMappingUpdate:
|
|
connect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCallbacks::handleImageToLedsMappingChange);
|
|
break;
|
|
case Subscription::ImageUpdate:
|
|
connect(_hyperion, &Hyperion::currentImage, this, &JsonCallbacks::handleImageUpdate);
|
|
break;
|
|
case Subscription::InstanceUpdate:
|
|
connect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCallbacks::handleInstanceChange);
|
|
break;
|
|
case Subscription::LedColorsUpdate:
|
|
connect(_hyperion, &Hyperion::rawLedColors, this, &JsonCallbacks::handleLedColorUpdate);
|
|
break;
|
|
case Subscription::LedsUpdate:
|
|
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleLedsConfigChange);
|
|
break;
|
|
case Subscription::LogMsgUpdate:
|
|
if (!_islogMsgStreamingActive)
|
|
{
|
|
handleLogMessageUpdate (Logger::T_LOG_MESSAGE{}); // needed to trigger log sending
|
|
_islogMsgStreamingActive = true;
|
|
Debug(_log, "log streaming activated for client %s", _peerAddress.toStdString().c_str());
|
|
}
|
|
connect(LoggerManager::getInstance().data(), &LoggerManager::newLogMessage, this, &JsonCallbacks::handleLogMessageUpdate);
|
|
break;
|
|
case Subscription::PrioritiesUpdate:
|
|
connect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCallbacks::handlePriorityUpdate);
|
|
break;
|
|
case Subscription::SettingsUpdate:
|
|
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleSettingsChange);
|
|
break;
|
|
case Subscription::TokenUpdate:
|
|
connect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCallbacks::handleTokenChange, Qt::AutoConnection);
|
|
break;
|
|
case Subscription::VideomodeUpdate:
|
|
connect(_hyperion, &Hyperion::newVideoMode, this, &JsonCallbacks::handleVideoModeChange);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
_subscribedCommands.insert(cmd);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JsonCallbacks::subscribe(const QString& cmd)
|
|
{
|
|
JsonApiSubscription subscription = ApiSubscriptionRegister::getSubscriptionInfo(cmd);
|
|
if (subscription.cmd == Subscription::Unknown)
|
|
{
|
|
return false;
|
|
}
|
|
return subscribe(subscription.cmd);
|
|
}
|
|
|
|
QStringList JsonCallbacks::subscribe(const QJsonArray& subscriptions)
|
|
{
|
|
QJsonArray subsArr;
|
|
if (subscriptions.contains("all"))
|
|
{
|
|
for (const auto& entry : getCommands(false))
|
|
{
|
|
subsArr.append(entry);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
subsArr = subscriptions;
|
|
}
|
|
|
|
QStringList invalidSubscriptions;
|
|
for (auto it = subsArr.begin(); it != subsArr.end(); ++it)
|
|
{
|
|
const QJsonValue& entry = *it;
|
|
if (!subscribe(entry.toString()))
|
|
{
|
|
invalidSubscriptions.append(entry.toString());
|
|
}
|
|
}
|
|
return invalidSubscriptions;
|
|
}
|
|
|
|
bool JsonCallbacks::unsubscribe(const Subscription::Type cmd)
|
|
{
|
|
_subscribedCommands.remove(cmd);
|
|
|
|
switch (cmd) {
|
|
case Subscription::AdjustmentUpdate:
|
|
disconnect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCallbacks::handleAdjustmentChange);
|
|
break;
|
|
case Subscription::ComponentsUpdate:
|
|
disconnect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCallbacks::handleComponentState);
|
|
break;
|
|
#if defined(ENABLE_EFFECTENGINE)
|
|
case Subscription::EffectsUpdate:
|
|
disconnect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCallbacks::handleEffectListChange);
|
|
break;
|
|
#endif
|
|
case Subscription::EventUpdate:
|
|
disconnect(EventHandler::getInstance().data(), &EventHandler::signalEvent, this, &JsonCallbacks::handleEventUpdate);
|
|
break;
|
|
case Subscription::ImageToLedMappingUpdate:
|
|
disconnect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCallbacks::handleImageToLedsMappingChange);
|
|
break;
|
|
case Subscription::ImageUpdate:
|
|
disconnect(_hyperion, &Hyperion::currentImage, this, &JsonCallbacks::handleImageUpdate);
|
|
break;
|
|
case Subscription::InstanceUpdate:
|
|
disconnect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCallbacks::handleInstanceChange);
|
|
break;
|
|
case Subscription::LedColorsUpdate:
|
|
disconnect(_hyperion, &Hyperion::rawLedColors, this, &JsonCallbacks::handleLedColorUpdate);
|
|
break;
|
|
case Subscription::LedsUpdate:
|
|
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleLedsConfigChange);
|
|
break;
|
|
case Subscription::LogMsgUpdate:
|
|
disconnect(LoggerManager::getInstance().data(), &LoggerManager::newLogMessage, this, &JsonCallbacks::handleLogMessageUpdate);
|
|
if (_islogMsgStreamingActive)
|
|
{
|
|
_islogMsgStreamingActive = false;
|
|
Debug(_log, "log streaming deactivated for client %s", _peerAddress.toStdString().c_str());
|
|
}
|
|
break;
|
|
case Subscription::PrioritiesUpdate:
|
|
disconnect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCallbacks::handlePriorityUpdate);
|
|
break;
|
|
case Subscription::SettingsUpdate:
|
|
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleSettingsChange);
|
|
break;
|
|
case Subscription::TokenUpdate:
|
|
disconnect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCallbacks::handleTokenChange);
|
|
break;
|
|
case Subscription::VideomodeUpdate:
|
|
disconnect(_hyperion, &Hyperion::newVideoMode, this, &JsonCallbacks::handleVideoModeChange);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool JsonCallbacks::unsubscribe(const QString& cmd)
|
|
{
|
|
JsonApiSubscription subscription = ApiSubscriptionRegister::getSubscriptionInfo(cmd);
|
|
if (subscription.cmd == Subscription::Unknown)
|
|
{
|
|
return false;
|
|
}
|
|
return unsubscribe(subscription.cmd);
|
|
}
|
|
|
|
QStringList JsonCallbacks::unsubscribe(const QJsonArray& subscriptions)
|
|
{
|
|
QJsonArray subsArr;
|
|
if (subscriptions.contains("all"))
|
|
{
|
|
for (const auto& entry : getCommands(false))
|
|
{
|
|
subsArr.append(entry);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
subsArr = subscriptions;
|
|
}
|
|
|
|
QStringList invalidSubscriptions;
|
|
for (auto it = subsArr.begin(); it != subsArr.end(); ++it)
|
|
{
|
|
const QJsonValue& entry = *it;
|
|
if (!unsubscribe(entry.toString()))
|
|
{
|
|
invalidSubscriptions.append(entry.toString());
|
|
}
|
|
}
|
|
return invalidSubscriptions;
|
|
}
|
|
|
|
void JsonCallbacks::resetSubscriptions()
|
|
{
|
|
const QSet<Subscription::Type> currentSubscriptions = _subscribedCommands;
|
|
for (QSet<Subscription::Type>::const_iterator it = currentSubscriptions.constBegin(); it != currentSubscriptions.constEnd(); ++it)
|
|
{
|
|
unsubscribe(*it);
|
|
}
|
|
}
|
|
|
|
void JsonCallbacks::setSubscriptionsTo(Hyperion* hyperion)
|
|
{
|
|
assert(hyperion);
|
|
|
|
// get current subs
|
|
const QSet<Subscription::Type> currSubs(_subscribedCommands);
|
|
|
|
// stop subs
|
|
resetSubscriptions();
|
|
|
|
// update pointer
|
|
_hyperion = hyperion;
|
|
_componentRegister = _hyperion->getComponentRegister();
|
|
_prioMuxer = _hyperion->getMuxerInstance();
|
|
|
|
// re-apply subs
|
|
for(const auto & entry : currSubs)
|
|
{
|
|
subscribe(entry);
|
|
}
|
|
}
|
|
|
|
QStringList JsonCallbacks::getCommands(bool fullList) const
|
|
{
|
|
QStringList commands;
|
|
for (JsonApiSubscription subscription : ApiSubscriptionRegister::getSubscriptionLookup())
|
|
{
|
|
if (fullList || subscription.isAll)
|
|
{
|
|
commands << Subscription::toString(subscription.cmd);
|
|
}
|
|
}
|
|
return commands;
|
|
}
|
|
|
|
QStringList JsonCallbacks::getSubscribedCommands() const
|
|
{
|
|
QStringList commands;
|
|
for (Subscription::Type cmd : _subscribedCommands)
|
|
{
|
|
commands << Subscription::toString(cmd);
|
|
}
|
|
return commands;
|
|
}
|
|
|
|
void JsonCallbacks::doCallback(Subscription::Type cmd, const QVariant& data)
|
|
{
|
|
QJsonObject obj;
|
|
obj["command"] = Subscription::toString(cmd);
|
|
|
|
if (Subscription::isInstanceSpecific(cmd))
|
|
{
|
|
obj["instance"] = _hyperion->getInstanceIndex();
|
|
}
|
|
|
|
if (data.userType() == QMetaType::QJsonArray) {
|
|
obj["data"] = data.toJsonArray();
|
|
} else {
|
|
obj["data"] = data.toJsonObject();
|
|
}
|
|
|
|
emit newCallback(obj);
|
|
}
|
|
|
|
void JsonCallbacks::handleComponentState(hyperion::Components comp, bool state)
|
|
{
|
|
QJsonObject data;
|
|
data["name"] = componentToIdString(comp);
|
|
data["enabled"] = state;
|
|
|
|
doCallback(Subscription::ComponentsUpdate, QVariant(data));
|
|
}
|
|
|
|
void JsonCallbacks::handlePriorityUpdate(int currentPriority, const PriorityMuxer::InputsMap& activeInputs)
|
|
{
|
|
QJsonObject data;
|
|
data["priorities"] = JsonInfo::getPrioritiestInfo(currentPriority, activeInputs);
|
|
data["priorities_autoselect"] = _hyperion->sourceAutoSelectEnabled();
|
|
|
|
doCallback(Subscription::PrioritiesUpdate, QVariant(data));
|
|
}
|
|
|
|
void JsonCallbacks::handleImageToLedsMappingChange(int mappingType)
|
|
{
|
|
QJsonObject data;
|
|
data["imageToLedMappingType"] = ImageProcessor::mappingTypeToStr(mappingType);
|
|
|
|
doCallback(Subscription::ImageToLedMappingUpdate, QVariant(data));
|
|
}
|
|
|
|
void JsonCallbacks::handleAdjustmentChange()
|
|
{
|
|
doCallback(Subscription::AdjustmentUpdate, JsonInfo::getAdjustmentInfo(_hyperion,_log));
|
|
}
|
|
|
|
void JsonCallbacks::handleVideoModeChange(VideoMode mode)
|
|
{
|
|
QJsonObject data;
|
|
data["videomode"] = QString(videoMode2String(mode));
|
|
doCallback(Subscription::VideomodeUpdate, QVariant(data));
|
|
}
|
|
|
|
#if defined(ENABLE_EFFECTENGINE)
|
|
void JsonCallbacks::handleEffectListChange()
|
|
{
|
|
QJsonObject effects;
|
|
effects["effects"] = JsonInfo::getEffects(_hyperion);
|
|
doCallback(Subscription::EffectsUpdate, QVariant(effects));
|
|
}
|
|
#endif
|
|
|
|
void JsonCallbacks::handleSettingsChange(settings::type type, const QJsonDocument& data)
|
|
{
|
|
QJsonObject dat;
|
|
if(data.isObject()) {
|
|
dat[typeToString(type)] = data.object();
|
|
} else {
|
|
dat[typeToString(type)] = data.array();
|
|
}
|
|
|
|
doCallback(Subscription::SettingsUpdate, QVariant(dat));
|
|
}
|
|
|
|
void JsonCallbacks::handleLedsConfigChange(settings::type type, const QJsonDocument& data)
|
|
{
|
|
if(type == settings::LEDS)
|
|
{
|
|
QJsonObject dat;
|
|
dat[typeToString(type)] = data.array();
|
|
doCallback(Subscription::LedsUpdate, QVariant(dat));
|
|
}
|
|
}
|
|
|
|
void JsonCallbacks::handleInstanceChange()
|
|
{
|
|
doCallback(Subscription::InstanceUpdate, JsonInfo::getInstanceInfo());
|
|
}
|
|
|
|
void JsonCallbacks::handleTokenChange(const QVector<AuthManager::AuthDefinition> &def)
|
|
{
|
|
QJsonArray arr;
|
|
for (const auto &entry : def)
|
|
{
|
|
QJsonObject sub;
|
|
sub["comment"] = entry.comment;
|
|
sub["id"] = entry.id;
|
|
sub["last_use"] = entry.lastUse;
|
|
arr.push_back(sub);
|
|
}
|
|
doCallback(Subscription::TokenUpdate, QVariant(arr));
|
|
}
|
|
|
|
void JsonCallbacks::handleLedColorUpdate(const std::vector<ColorRgb> &ledColors)
|
|
{
|
|
QJsonObject result;
|
|
QJsonArray leds;
|
|
|
|
for (const auto &color : ledColors)
|
|
{
|
|
leds << QJsonValue(color.red) << QJsonValue(color.green) << QJsonValue(color.blue);
|
|
}
|
|
result["leds"] = leds;
|
|
|
|
doCallback(Subscription::LedColorsUpdate, QVariant(result));
|
|
}
|
|
|
|
void JsonCallbacks::handleImageUpdate(const Image<ColorRgb> &image)
|
|
{
|
|
QImage jpgImage(reinterpret_cast<const uchar*>(image.memptr()), image.width(), image.height(), qsizetype(3) * image.width(), QImage::Format_RGB888);
|
|
QByteArray byteArray;
|
|
QBuffer buffer(&byteArray);
|
|
buffer.open(QIODevice::WriteOnly);
|
|
jpgImage.save(&buffer, "jpg");
|
|
|
|
QJsonObject result;
|
|
result["image"] = "data:image/jpg;base64," + QString(byteArray.toBase64());
|
|
|
|
doCallback(Subscription::ImageUpdate, QVariant(result));
|
|
}
|
|
|
|
void JsonCallbacks::handleLogMessageUpdate(const Logger::T_LOG_MESSAGE &msg)
|
|
{
|
|
QJsonObject result;
|
|
QJsonObject message;
|
|
QJsonArray messageArray;
|
|
|
|
if (!_islogMsgStreamingActive)
|
|
{
|
|
_islogMsgStreamingActive = true;
|
|
QMetaObject::invokeMethod(LoggerManager::getInstance().data(), "getLogMessageBuffer",
|
|
Qt::DirectConnection,
|
|
Q_RETURN_ARG(QJsonArray, messageArray),
|
|
Q_ARG(Logger::LogLevel, _log->getLogLevel()));
|
|
}
|
|
else
|
|
{
|
|
message["loggerName"] = msg.loggerName;
|
|
message["loggerSubName"] = msg.loggerSubName;
|
|
message["function"] = msg.function;
|
|
message["line"] = QString::number(msg.line);
|
|
message["fileName"] = msg.fileName;
|
|
message["message"] = msg.message;
|
|
message["levelString"] = msg.levelString;
|
|
message["utime"] = QString::number(msg.utime);
|
|
|
|
messageArray.append(message);
|
|
}
|
|
result.insert("messages", messageArray);
|
|
|
|
doCallback(Subscription::LogMsgUpdate, QVariant(result));
|
|
}
|
|
|
|
void JsonCallbacks::handleEventUpdate(const Event &event)
|
|
{
|
|
QJsonObject result;
|
|
|
|
result["event"] = eventToString(event);
|
|
|
|
doCallback(Subscription::EventUpdate, QVariant(result));
|
|
}
|
|
|