KDEAmbi/hgx11.cpp
Tobias J. Endres b6239241c9 Fix: Malformed JSON due to incorrect priority string construction
The JSON output sent to the Hyperion server was malformed, specifically
the "priority" field, leading to an "unterminated object" error.
This was caused by the _hyperionPriority_m variable (and
subsequently _priority_m in hgx11net) containing the literal
"priority:" string, which was then redundantly added during JSON
string construction.

This commit modifies:
- hgx11.cpp: To store only the numerical priority value in
  _hyperionPriority_m.
- hgx11net.cpp: To explicitly add the "priority:" key during JSON
  string construction in all relevant functions (clearLeds,
  setLedColor, _colorAdjustment, _thresholdAdjustment,
  _transformdAdjustment, _temperatureAdjustment, and _setImgSize).

This ensures that the generated JSON is correctly formatted.
2025-08-14 02:26:06 +02:00

201 lines
6.8 KiB
C++

#include "hgx11.h"
// public
hgx11::hgx11(QHash<QString, QString> opts)
{
QString addr = "localhost";
unsigned short port = 19444;
unsigned short scale = 8;
unsigned short frameskip = 0;
unsigned short priority = 100;
const char * filter = FilterNearest;
QString redAdjust = "", greenAdjust = "", blueAdjust = "";
QString temperature = "", threshold = "", transform = "";
QHashIterator<QString, QString> i(opts);
while (i.hasNext()) {
i.next();
if ((i.key() == "a" || i.key() == "address") && !(i.value().isNull() && i.value().isEmpty())) {
addr = i.value();
} else if ((i.key() == "p" || i.key() == "port") && i.value().toUShort()) {
port = i.value().toUShort();
} else if ((i.key() == "c" || i.key() == "priority") && (i.value().toUShort() && i.value().toUShort() <= 255)) {
priority = i.value().toUShort();
} else if ((i.key() == "s" || i.key() == "scale") && i.value().toUShort()) {
scale = i.value().toUShort();
} else if ((i.key() == "f" || i.key() == "frameskip") && (i.value().toUShort() && i.value().toUShort() <= 255)) {
frameskip = i.value().toUShort();
} else if ((i.key() == "i" || i.key() == "inactive") && i.value().toInt()) {
_inactiveTime_m = (i.value().toInt() * 1000);
} else if ((i.key() == "j" || i.key() == "inactivetype") && i.value().toInt() == 1) {
_inactiveXss_m = true;
} else if (i.key() == "r" || i.key() == "redadjust") {
redAdjust = _parseColorArr(i.value(), 1);
} else if (i.key() == "g" || i.key() == "greenadjust") {
greenAdjust = _parseColorArr(i.value(), 1);
} else if (i.key() == "b" || i.key() == "blueadjust") {
blueAdjust = _parseColorArr(i.value(), 1);
} else if (i.key() == "t" || i.key() == "temperature") {
temperature = _parseColorArr(i.value(), 1);
} else if (i.key() == "d" || i.key() == "threshold") {
threshold = _parseColorArr(i.value(), 0);
} else if ((i.key() == "l" || i.key() == "transform") && _parseColorArr(i.value(), 0) != "") {
transform = i.value();
} else if ((i.key() == "x" || i.key() == "scalefilter") && i.value().toInt()) {
switch (i.value().toInt()) {
case 1:
filter = FilterBilinear;
break;
case 2:
filter = FilterFast;
break;
case 3:
filter = FilterGood;
break;
case 4:
filter = FilterBest;
break;
}
}
}
// _hyperionPriority_m now stores only the priority value, not the "priority:" key.
_hyperionPriority_m = QString::number(priority);
_display_p = XOpenDisplay(nullptr);
if(_display_p == nullptr){
qCritical() << "Failed to open X11 display";
return;
}
_grabber_p = new hgx11grab(_display_p, scale, filter);
_hclient_p = new hgx11net(addr, port, _hyperionPriority_m);
_damage_p = new hgx11damage(&_grabbed_m, frameskip);
if (_inactiveXss_m) {
_screensaver_p = new hgx11screensaver(_display_p);
_inactiveTimeXss_m = ulong(_inactiveTime_m);
}
_setImgSize();
_hclient_p->ledAdjustments(redAdjust, greenAdjust, blueAdjust, temperature, threshold, transform);
connect(_damage_p, SIGNAL(damageDetected()), this, SLOT(_grabImage()));
connect(_grabber_p, SIGNAL(scaleChanged()), this, SLOT(_setImgSize()));
connect(_grabber_p, SIGNAL(imageCreated()), this, SLOT(_sendImage()));
_grabActive_m = true;
if (_inactiveTime_m) {
_timer_p = new QTimer(this);
if (!_inactiveXss_m) {
connect(_timer_p, SIGNAL(timeout()), this, SLOT(_inActivity()));
connect(_damage_p, SIGNAL(damageDetected()), this, SLOT(_activity()));
_timer_p->start(_inactiveTime_m);
} else {
connect(_timer_p, SIGNAL(timeout()), this, SLOT(_checkXss()));
_timer_p->start(1000);
}
}
_damage_p->start();
}
hgx11::~hgx11()
{
_grabbed_m.wakeAll();
_timer_p->stop();
disconnect(_damage_p, SIGNAL(damageDetected()), _grabber_p, SLOT(grabFrame()));
disconnect(_grabber_p, SIGNAL(scaleChanged()), this, SLOT(_setImgSize()));
disconnect(_grabber_p, SIGNAL(imageCreated()), this, SLOT(_sendImage()));
if (!_inactiveXss_m) {
disconnect(_timer_p, SIGNAL(timeout()), this, SLOT(_inActivity()));
disconnect(_damage_p, SIGNAL(damageDetected()), this, SLOT(_activity()));
} else {
disconnect(_timer_p, SIGNAL(timeout()), this, SLOT(_checkXss()));
delete _screensaver_p;
}
if (_display_p != nullptr) {
XCloseDisplay(_display_p);
}
delete _hclient_p;
_damage_p->terminate();
while (!_damage_p->isFinished()) {}
delete _damage_p;
delete _grabber_p;
delete _timer_p;
}
// private
QString hgx11::_parseColorArr(QString value, bool isInt)
{
QStringList values = value.split(',');
if (values.size() != 3) {
return "";
}
value = "[";
for (int i = 0; i < 3; i++) {
if (isInt && (values.at(i).toInt() < 0 || values.at(i).toInt() > 255)) {
return "";
}
if (!isInt && (values.at(i).toDouble() < 0.0 || values.at(i).toDouble() > 1.0)) {
return "";
}
value.append(values.at(i));
value.append(",");
}
value.chop(1);
value.append("]");
return value;
}
// private slots
void hgx11::_grabImage()
{
_grabber_p->grabFrame();
_grabbed_m.wakeAll();
}
void hgx11::_sendImage()
{
_hclient_p->sendImage(_grabber_p->imgdata_m);
}
void hgx11::_inActivity()
{
_hclient_p->clearLeds();
}
void hgx11::_activity()
{
_timer_p->stop();
_timer_p->start(_inactiveTime_m);
}
void hgx11::_setImgSize()
{
_hclient_p->imgCmdBuf.clear();
_hclient_p->imgCmdBuf.append("{"command":"image","priority":").append(_hyperionPriority_m.toUtf8()).append(","imageheight":");
_hclient_p->imgCmdBuf.append(QString::number(_grabber_p->getDest_height()).toUtf8());
_hclient_p->imgCmdBuf.append(",\"imagewidth\":");
_hclient_p->imgCmdBuf.append(QString::number(_grabber_p->getDest_width()).toUtf8());
_hclient_p->imgCmdBuf.append(",\"imagedata\":\"");
}
void hgx11::_checkXss()
{
if (_screensaver_p->lastX11ActivitySeconds() < _inactiveTimeXss_m) {
if (!_grabActive_m) {
connect(_damage_p, SIGNAL(damageDetected()), _grabber_p, SLOT(grabFrame()));
_grabActive_m = true;
}
return;
}
if (_grabActive_m) {
disconnect(_damage_p, SIGNAL(damageDetected()), _grabber_p, SLOT(grabFrame()));
_grabActive_m = false;
_inActivity();
}
}