* Fix #604 and #605

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* clear current prio on color command

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* Fix QTimer threading issues

* Call QTimer start() stop() from QEvent

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* send initial color/image to WebUI
hide error message when opening webbrowser

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* added streaming timer to update WebUI Preview

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* remove QMetaObject::invokeMethod()

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* added parent to streaming timers

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* header cleanup
This commit is contained in:
Paulchen Panther
2019-08-24 22:53:30 +02:00
committed by brindosch
parent c419f305f3
commit 24495bbc65
8 changed files with 150 additions and 74 deletions

View File

@@ -19,7 +19,9 @@
"type" : "bool"
},
"interval": {
"type" : "integer"
"type" : "integer",
"required" : false,
"minimum": 50
}
},

View File

@@ -12,17 +12,16 @@
#include <QImage>
#include <QBuffer>
#include <QByteArray>
#include <QDateTime>
#include <QHostInfo>
#include <QMutexLocker>
#include <QTimer>
// hyperion includes
#include <utils/jsonschema/QJsonFactory.h>
#include <utils/SysInfo.h>
#include <HyperionConfig.h>
#include <utils/ColorSys.h>
#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/JsonUtils.h>
@@ -53,8 +52,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _hyperion(nullptr)
, _jsonCB(nullptr)
, _streaming_logging_activated(false)
, _image_stream_timeout(0)
, _led_stream_timeout(0)
, _imageStreamTimer(new QTimer(this))
, _ledStreamTimer(new QTimer(this))
{
Q_INIT_RESOURCE(JSONRPC_schemas);
@@ -1018,28 +1017,68 @@ void JsonAPI::handleLedColorsCommand(const QJsonObject& message, const QString &
// create result
QString subcommand = message["subcommand"].toString("");
// max 20 Hz (50ms) interval for streaming (default: 10 Hz (100ms))
qint64 streaming_interval = qMax(message["interval"].toInt(100), 50);
if (subcommand == "ledstream-start")
{
_streaming_leds_reply["success"] = true;
_streaming_leds_reply["command"] = command+"-ledstream-update";
_streaming_leds_reply["tan"] = tan;
connect(_hyperion, &Hyperion::rawLedColors, this, &JsonAPI::streamLedcolorsUpdate, Qt::UniqueConnection);
connect(_hyperion, &Hyperion::rawLedColors, this, [=](const std::vector<ColorRgb>& ledValues)
{
_currentLedValues = ledValues;
// necessary because Qt::UniqueConnection for lambdas does not work until 5.9
// see: https://bugreports.qt.io/browse/QTBUG-52438
if (!_ledStreamConnection)
_ledStreamConnection = connect(_ledStreamTimer, &QTimer::timeout, this, [=]()
{
emit streamLedcolorsUpdate(_currentLedValues);
}, Qt::UniqueConnection);
// start the timer
if (!_ledStreamTimer->isActive() || _ledStreamTimer->interval() != streaming_interval)
_ledStreamTimer->start(streaming_interval);
}, Qt::UniqueConnection);
}
else if (subcommand == "ledstream-stop")
{
disconnect(_hyperion, &Hyperion::rawLedColors, this, &JsonAPI::streamLedcolorsUpdate);
disconnect(_hyperion, &Hyperion::rawLedColors, this, 0);
_ledStreamTimer->stop();
disconnect(_ledStreamConnection);
}
else if (subcommand == "imagestream-start")
{
_streaming_image_reply["success"] = true;
_streaming_image_reply["command"] = command+"-imagestream-update";
_streaming_image_reply["tan"] = tan;
connect(_hyperion, &Hyperion::currentImage, this, &JsonAPI::setImage, Qt::UniqueConnection);
connect(_hyperion, &Hyperion::currentImage, this, [=](const Image<ColorRgb>& image)
{
_currentImage = image;
// necessary because Qt::UniqueConnection for lambdas does not work until 5.9
// see: https://bugreports.qt.io/browse/QTBUG-52438
if (!_imageStreamConnection)
_imageStreamConnection = connect(_imageStreamTimer, &QTimer::timeout, this, [=]()
{
emit setImage(_currentImage);
}, Qt::UniqueConnection);
// start timer
if (!_imageStreamTimer->isActive() || _imageStreamTimer->interval() != streaming_interval)
_imageStreamTimer->start(streaming_interval);
}, Qt::UniqueConnection);
_hyperion->update();
}
else if (subcommand == "imagestream-stop")
{
disconnect(_hyperion, &Hyperion::currentImage, this, &JsonAPI::setImage);
disconnect(_hyperion, &Hyperion::currentImage, this, 0);
_imageStreamTimer->stop();
disconnect(_imageStreamConnection);
}
else
{
@@ -1420,52 +1459,40 @@ void JsonAPI::sendErrorReply(const QString &error, const QString &command, const
emit callbackMessage(reply);
}
void JsonAPI::streamLedcolorsUpdate(const std::vector<ColorRgb>& ledColors)
{
QMutexLocker lock(&_led_stream_mutex);
if ( (_led_stream_timeout+100) < QDateTime::currentMSecsSinceEpoch() )
QJsonObject result;
QJsonArray leds;
for(auto color = ledColors.begin(); color != ledColors.end(); ++color)
{
_led_stream_timeout = QDateTime::currentMSecsSinceEpoch();
QJsonObject result;
QJsonArray leds;
for(auto color = ledColors.begin(); color != ledColors.end(); ++color)
{
QJsonObject item;
item["index"] = int(color - ledColors.begin());
item["red"] = color->red;
item["green"] = color->green;
item["blue"] = color->blue;
leds.append(item);
}
result["leds"] = leds;
_streaming_leds_reply["result"] = result;
// send the result
emit callbackMessage(_streaming_leds_reply);
QJsonObject item;
item["index"] = int(color - ledColors.begin());
item["red"] = color->red;
item["green"] = color->green;
item["blue"] = color->blue;
leds.append(item);
}
result["leds"] = leds;
_streaming_leds_reply["result"] = result;
// send the result
emit callbackMessage(_streaming_leds_reply);
}
void JsonAPI::setImage(const Image<ColorRgb> & image)
{
QMutexLocker lock(&_image_stream_mutex);
if ( (_image_stream_timeout+100) < QDateTime::currentMSecsSinceEpoch() )
{
_image_stream_timeout = QDateTime::currentMSecsSinceEpoch();
QImage jpgImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
jpgImage.save(&buffer, "jpg");
QImage jpgImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
jpgImage.save(&buffer, "jpg");
QJsonObject result;
result["image"] = "data:image/jpg;base64,"+QString(ba.toBase64());
_streaming_image_reply["result"] = result;
emit callbackMessage(_streaming_image_reply);
}
QJsonObject result;
result["image"] = "data:image/jpg;base64,"+QString(ba.toBase64());
_streaming_image_reply["result"] = result;
emit callbackMessage(_streaming_image_reply);
}
void JsonAPI::incommingLogMessage(const Logger::T_LOG_MESSAGE &msg)

View File

@@ -368,6 +368,9 @@ void Hyperion::setColor(const int priority, const ColorRgb &color, const int tim
// create led vector from single color
std::vector<ColorRgb> ledColors(_ledString.leds().size(), color);
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
clear(priority);
// register color
registerInput(priority, hyperion::COMP_COLOR, origin);

View File

@@ -72,7 +72,7 @@ int LinearColorSmoothing::write(const std::vector<ColorRgb> &ledValues)
_previousTime = QDateTime::currentMSecsSinceEpoch();
_previousValues = ledValues;
_timer->start();
QMetaObject::invokeMethod(_timer, "start", Qt::QueuedConnection, Q_ARG(int, _updateInterval));
}
else
{
@@ -182,7 +182,7 @@ void LinearColorSmoothing::setEnable(bool enable)
{
if (!enable)
{
_timer->stop();
QMetaObject::invokeMethod(_timer, "stop", Qt::QueuedConnection);
_previousValues.clear();
}
// update comp register
@@ -218,10 +218,9 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
if (_cfgList[cfg].updateInterval != _updateInterval)
{
_timer->stop();
QMetaObject::invokeMethod(_timer, "stop", Qt::QueuedConnection);
_updateInterval = _cfgList[cfg].updateInterval;
_timer->setInterval(_updateInterval);
_timer->start();
QMetaObject::invokeMethod(_timer, "start", Qt::QueuedConnection, Q_ARG(int, _updateInterval));
}
_currentConfigId = cfg;
//DebugIf( enabled() && !_pause, _log, "set smoothing cfg: %d, interval: %d ms, settlingTime: %d ms, updateDelay: %d frames", _currentConfigId, _updateInterval, _settlingTime, _outputDelay );

View File

@@ -185,6 +185,7 @@ bool PriorityMuxer::setInput(const int priority, const std::vector<ColorRgb>& le
// update input
input.timeoutTime_ms = timeout_ms;
input.ledColors = ledColors;
input.image.clear();
// emit active change
if(activeChange)
@@ -224,6 +225,7 @@ bool PriorityMuxer::setInputImage(const int priority, const Image<ColorRgb>& ima
// update input
input.timeoutTime_ms = timeout_ms;
input.image = image;
input.ledColors.clear();
// emit active change
if(activeChange)