even more changes

Signed-off-by: Paulchen-Panther <Paulchen--Panter@gmx.net>
This commit is contained in:
Paulchen-Panther
2018-12-28 18:12:45 +01:00
parent 3700566d10
commit 2a77f6f012
99 changed files with 2610 additions and 673 deletions

View File

@@ -8,6 +8,7 @@ add_subdirectory(commandline)
add_subdirectory(blackborder)
add_subdirectory(jsonserver)
add_subdirectory(protoserver)
add_subdirectory(flatbufserver)
add_subdirectory(bonjour)
add_subdirectory(boblightserver)
add_subdirectory(udplistener)

21
libsrc/api/CMakeLists.txt Normal file
View File

@@ -0,0 +1,21 @@
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/api)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/api)
FILE ( GLOB_RECURSE Api_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" )
set(Api_RESOURCES ${CURRENT_SOURCE_DIR}/JSONRPC_schemas.qrc )
add_library(hyperion-api
${Api_SOURCES}
${Api_RESOURCES}
)
target_link_libraries(hyperion-api
hyperion
hyperion-utils
Qt5::Core
Qt5::Gui
Qt5::Network
)

1069
libsrc/api/JsonAPI.cpp Normal file

File diff suppressed because it is too large Load Diff

304
libsrc/api/JsonCB.cpp Normal file
View File

@@ -0,0 +1,304 @@
// proj incl
#include <api/JsonCB.h>
// hyperion
#include <hyperion/Hyperion.h>
// components
#include <hyperion/ComponentRegister.h>
// bonjour wrapper
#include <bonjour/bonjourbrowserwrapper.h>
// priorityMuxer
#include <hyperion/PriorityMuxer.h>
#include <utils/ColorSys.h>
#include <QDateTime>
// Image to led map helper
#include <hyperion/ImageProcessor.h>
using namespace hyperion;
JsonCB::JsonCB(QObject* parent)
: QObject(parent)
, _hyperion(Hyperion::getInstance())
, _componentRegister(& _hyperion->getComponentRegister())
, _bonjour(BonjourBrowserWrapper::getInstance())
, _prioMuxer(_hyperion->getMuxerInstance())
{
_availableCommands << "components-update" << "sessions-update" << "priorities-update" << "imageToLedMapping-update"
<< "adjustment-update" << "videomode-update" << "effects-update" << "settings-update";
}
bool JsonCB::subscribeFor(const QString& type)
{
if(!_availableCommands.contains(type))
return false;
if(type == "components-update")
{
_subscribedCommands << type;
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCB::handleComponentState, Qt::UniqueConnection);
}
if(type == "sessions-update")
{
_subscribedCommands << type;
connect(_bonjour, &BonjourBrowserWrapper::browserChange, this, &JsonCB::handleBonjourChange, Qt::UniqueConnection);
}
if(type == "priorities-update")
{
_subscribedCommands << type;
connect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCB::handlePriorityUpdate, Qt::UniqueConnection);
connect(_prioMuxer, &PriorityMuxer::autoSelectChanged, this, &JsonCB::handlePriorityUpdate, Qt::UniqueConnection);
}
if(type == "imageToLedMapping-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCB::handleImageToLedsMappingChange, Qt::UniqueConnection);
}
if(type == "adjustment-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCB::handleAdjustmentChange, Qt::UniqueConnection);
}
if(type == "videomode-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::newVideoMode, this, &JsonCB::handleVideoModeChange, Qt::UniqueConnection);
}
if(type == "effects-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCB::handleEffectListChange, Qt::UniqueConnection);
}
if(type == "settings-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleSettingsChange, Qt::UniqueConnection);
}
return true;
}
void JsonCB::doCallback(const QString& cmd, const QVariant& data)
{
QJsonObject obj;
obj["command"] = cmd;
if(static_cast<QMetaType::Type>(data.type()) == QMetaType::QJsonArray)
obj["data"] = data.toJsonArray();
else
obj["data"] = data.toJsonObject();
emit newCallback(obj);
}
void JsonCB::handleComponentState(const hyperion::Components comp, const bool state)
{
QJsonObject data;
data["name"] = componentToIdString(comp);
data["enabled"] = state;
doCallback("components-update", QVariant(data));
}
void JsonCB::handleBonjourChange(const QMap<QString,BonjourRecord>& bRegisters)
{
QJsonArray data;
for (const auto & session: bRegisters)
{
if (session.port<0) continue;
QJsonObject item;
item["name"] = session.serviceName;
item["type"] = session.registeredType;
item["domain"] = session.replyDomain;
item["host"] = session.hostName;
item["address"]= session.address;
item["port"] = session.port;
data.append(item);
}
doCallback("sessions-update", QVariant(data));
}
void JsonCB::handlePriorityUpdate()
{
QJsonObject data;
QJsonArray priorities;
uint64_t now = QDateTime::currentMSecsSinceEpoch();
QList<int> activePriorities = _prioMuxer->getPriorities();
activePriorities.removeAll(255);
int currentPriority = _prioMuxer->getCurrentPriority();
foreach (int priority, activePriorities) {
const Hyperion::InputInfo priorityInfo = _prioMuxer->getInputInfo(priority);
QJsonObject item;
item["priority"] = priority;
if (int(priorityInfo.timeoutTime_ms - now) > -1 )
{
item["duration_ms"] = int(priorityInfo.timeoutTime_ms - now);
}
// owner has optional informations to the component
if(!priorityInfo.owner.isEmpty())
item["owner"] = priorityInfo.owner;
item["componentId"] = QString(hyperion::componentToIdString(priorityInfo.componentId));
item["origin"] = priorityInfo.origin;
item["active"] = (priorityInfo.timeoutTime_ms >= -1);
item["visible"] = (priority == currentPriority);
if(priorityInfo.componentId == hyperion::COMP_COLOR && !priorityInfo.ledColors.empty())
{
QJsonObject LEDcolor;
// add RGB Value to Array
QJsonArray RGBValue;
RGBValue.append(priorityInfo.ledColors.begin()->red);
RGBValue.append(priorityInfo.ledColors.begin()->green);
RGBValue.append(priorityInfo.ledColors.begin()->blue);
LEDcolor.insert("RGB", RGBValue);
uint16_t Hue;
float Saturation, Luminace;
// add HSL Value to Array
QJsonArray HSLValue;
ColorSys::rgb2hsl(priorityInfo.ledColors.begin()->red,
priorityInfo.ledColors.begin()->green,
priorityInfo.ledColors.begin()->blue,
Hue, Saturation, Luminace);
HSLValue.append(Hue);
HSLValue.append(Saturation);
HSLValue.append(Luminace);
LEDcolor.insert("HSL", HSLValue);
item["value"] = LEDcolor;
}
priorities.append(item);
}
data["priorities"] = priorities;
data["priorities_autoselect"] = _hyperion->sourceAutoSelectEnabled();
doCallback("priorities-update", QVariant(data));
}
void JsonCB::handleImageToLedsMappingChange(const int& mappingType)
{
QJsonObject data;
data["imageToLedMappingType"] = ImageProcessor::mappingTypeToStr(mappingType);
doCallback("imageToLedMapping-update", QVariant(data));
}
void JsonCB::handleAdjustmentChange()
{
QJsonArray adjustmentArray;
for (const QString& adjustmentId : _hyperion->getAdjustmentIds())
{
const ColorAdjustment * colorAdjustment = _hyperion->getAdjustment(adjustmentId);
if (colorAdjustment == nullptr)
{
continue;
}
QJsonObject adjustment;
adjustment["id"] = adjustmentId;
QJsonArray whiteAdjust;
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentR());
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentG());
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentB());
adjustment.insert("white", whiteAdjust);
QJsonArray redAdjust;
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentR());
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentG());
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentB());
adjustment.insert("red", redAdjust);
QJsonArray greenAdjust;
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentR());
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentG());
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentB());
adjustment.insert("green", greenAdjust);
QJsonArray blueAdjust;
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentR());
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentG());
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentB());
adjustment.insert("blue", blueAdjust);
QJsonArray cyanAdjust;
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentR());
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentG());
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentB());
adjustment.insert("cyan", cyanAdjust);
QJsonArray magentaAdjust;
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentR());
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentG());
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentB());
adjustment.insert("magenta", magentaAdjust);
QJsonArray yellowAdjust;
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentR());
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentG());
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentB());
adjustment.insert("yellow", yellowAdjust);
adjustment["backlightThreshold"] = colorAdjustment->_rgbTransform.getBacklightThreshold();
adjustment["backlightColored"] = colorAdjustment->_rgbTransform.getBacklightColored();
adjustment["brightness"] = colorAdjustment->_rgbTransform.getBrightness();
adjustment["brightnessCompensation"] = colorAdjustment->_rgbTransform.getBrightnessCompensation();
adjustment["gammaRed"] = colorAdjustment->_rgbTransform.getGammaR();
adjustment["gammaGreen"] = colorAdjustment->_rgbTransform.getGammaG();
adjustment["gammaBlue"] = colorAdjustment->_rgbTransform.getGammaB();
adjustmentArray.append(adjustment);
}
doCallback("adjustment-update", QVariant(adjustmentArray));
}
void JsonCB::handleVideoModeChange(const VideoMode& mode)
{
QJsonObject data;
data["videomode"] = QString(videoMode2String(mode));
doCallback("videomode-update", QVariant(data));
}
void JsonCB::handleEffectListChange()
{
QJsonArray effectList;
QJsonObject effects;
const std::list<EffectDefinition> & effectsDefinitions = _hyperion->getEffects();
for (const EffectDefinition & effectDefinition : effectsDefinitions)
{
QJsonObject effect;
effect["name"] = effectDefinition.name;
effect["file"] = effectDefinition.file;
effect["script"] = effectDefinition.script;
effect["args"] = effectDefinition.args;
effectList.append(effect);
};
effects["effects"] = effectList;
doCallback("effects-update", QVariant(effects));
}
void JsonCB::handleSettingsChange(const settings::type& type, const QJsonDocument& data)
{
QJsonObject dat;
if(data.isObject())
dat[typeToString(type)] = data.object();
else
dat[typeToString(type)] = data.array();
doCallback("settings-update", QVariant(dat));
}

View File

@@ -50,12 +50,16 @@ void BlackBorderProcessor::handleSettingsUpdate(const settings::type& type, cons
_maxInconsistentCnt = obj["maxInconsistentCnt"].toInt(10);
_blurRemoveCnt = obj["blurRemoveCnt"].toInt(1);
_detectionMode = obj["mode"].toString("default");
const double newThreshold = obj["threshold"].toDouble(5.0)/100.0;
if(_oldThreshold != obj["threshold"].toDouble(5.0/100))
if(_oldThreshold != newThreshold)
{
_oldThreshold = obj["threshold"].toDouble(5.0/100);
if(_detector != nullptr) delete _detector;
_detector = new BlackBorderDetector(obj["threshold"].toDouble(5.0/100));
_oldThreshold = newThreshold;
if(_detector != nullptr)
delete _detector;
_detector = new BlackBorderDetector(newThreshold);
}
Debug(Logger::getInstance("BLACKBORDER"), "Set mode to: %s", QSTRING_CSTR(_detectionMode));

View File

@@ -15,23 +15,22 @@
#include <QHostInfo>
// hyperion util includes
//#include "hyperion/ImageProcessorFactory.h"
//#include "hyperion/ImageProcessor.h"
#include "utils/ColorRgb.h"
#include <hyperion/ImageProcessor.h>
#include "HyperionConfig.h"
#include <hyperion/Hyperion.h>
// project includes
#include "BoblightClientConnection.h"
BoblightClientConnection::BoblightClientConnection(QTcpSocket *socket, const int priority)
BoblightClientConnection::BoblightClientConnection(Hyperion* hyperion, QTcpSocket *socket, const int priority)
: QObject()
, _locale(QLocale::C)
, _socket(socket)
//, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
, _hyperion(Hyperion::getInstance())
, _imageProcessor(hyperion->getImageProcessor())
, _hyperion(hyperion)
, _receiveBuffer()
, _priority(priority)
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK)
, _ledColors(hyperion->getLedCount(), ColorRgb::BLACK)
, _log(Logger::getInstance("BOBLIGHT"))
, _clientAddress(QHostInfo::fromName(socket->peerAddress().toString()).hostName())
{
@@ -227,11 +226,11 @@ void BoblightClientConnection::sendLightMessage()
int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount());
sendMessage(QByteArray(buffer, n));
//double h0, h1, v0, v1;
double h0, h1, v0, v1;
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
{
//_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
//n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
//sendMessage(QByteArray(buffer, n));
_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
sendMessage(QByteArray(buffer, n));
}
}

View File

@@ -5,9 +5,12 @@
#include <QTcpSocket>
#include <QLocale>
// Hyperion includes
#include <hyperion/Hyperion.h>
// utils includes
#include <utils/Logger.h>
#include <utils/ColorRgb.h>
class ImageProcessor;
class Hyperion;
///
/// The Connection object created by \a BoblightServer when a new connection is establshed
@@ -22,7 +25,7 @@ public:
/// @param socket The Socket object for this connection
/// @param hyperion The Hyperion server
///
BoblightClientConnection(QTcpSocket * socket, const int priority);
BoblightClientConnection(Hyperion* hyperion, QTcpSocket * socket, const int priority);
///
/// Destructor
@@ -74,6 +77,9 @@ private:
/// The TCP-Socket that is connected tot the boblight-client
QTcpSocket * _socket;
/// The processor for translating images to led-values
ImageProcessor * _imageProcessor;
/// Link to Hyperion for writing led-values to a priority channel
Hyperion * _hyperion;

View File

@@ -12,9 +12,9 @@
using namespace hyperion;
BoblightServer::BoblightServer(const QJsonDocument& config)
BoblightServer::BoblightServer(Hyperion* hyperion,const QJsonDocument& config)
: QObject()
, _hyperion(Hyperion::getInstance())
, _hyperion(hyperion)
, _server(new QTcpServer(this))
, _openConnections()
, _priority(0)
@@ -96,7 +96,7 @@ void BoblightServer::newConnection()
{
Info(_log, "new connection");
_hyperion->registerInput(_priority, hyperion::COMP_BOBLIGHTSERVER, QString("Boblight@%1").arg(socket->peerAddress().toString()));
BoblightClientConnection * connection = new BoblightClientConnection(socket, _priority);
BoblightClientConnection * connection = new BoblightClientConnection(_hyperion, socket, _priority);
_openConnections.insert(connection);
// register slot for cleaning up after the connection closed

View File

@@ -34,8 +34,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <utils/Logger.h>
#include <HyperionConfig.h>
#include <hyperion/Hyperion.h>
#include <utils/Stats.h>
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0)
@@ -54,10 +53,11 @@ BonjourServiceRegister::~BonjourServiceRegister()
void BonjourServiceRegister::registerService(const QString& service, const int& port)
{
_port = port;
// zeroconf $configname@$hostname:port
QString prettyName = Hyperion::getInstance()->getQJsonConfig()["general"].toObject()["name"].toString();
// TODO add name of the main instance
registerService(
BonjourRecord(prettyName+"@"+QHostInfo::localHostName()+ ":" + QString::number(port),
BonjourRecord(QHostInfo::localHostName()+ ":" + QString::number(port),
service,
QString()
),

View File

@@ -117,6 +117,6 @@ void BonjourServiceResolver::bonjourResolveReply(DNSServiceRef sdRef, DNSService
void BonjourServiceResolver::finishConnect(const QHostInfo &hostInfo)
{
emit bonjourRecordResolved(hostInfo, bonjourPort);
emit bonjourRecordResolved(hostInfo, bonjourPort);
QMetaObject::invokeMethod(this, "cleanupResolve", Qt::QueuedConnection);
}

View File

@@ -1,4 +1,4 @@
find_package(PythonLibs 3.4 REQUIRED)
find_package(PythonLibs 3.5 REQUIRED)
# Include the python directory. Also include the parent (which is for example /usr/include)
# which may be required when it is not includes by the (cross-) compiler by default.

View File

@@ -81,7 +81,7 @@ void Effect::run()
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _hyperion->getLedCount()));
// add minimumWriteTime variable to the interpreter
PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", Hyperion::getInstance()->getLatchTime()));
PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", _hyperion->getLatchTime()));
// add a args variable to the interpreter
PyObject_SetAttrString(module, "args", EffectModule::json2python(_args));

View File

@@ -29,7 +29,6 @@ FlatBufferClient::FlatBufferClient(QTcpSocket* socket, const int &timeout, QObje
void FlatBufferClient::readyRead()
{
qDebug()<<"readyRead";
_timeoutTimer->start();
_receiveBuffer += _socket->readAll();
@@ -37,7 +36,6 @@ void FlatBufferClient::readyRead()
// check if we can read a header
while(_receiveBuffer.size() >= 4)
{
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
@@ -47,10 +45,11 @@ void FlatBufferClient::readyRead()
// check if we can read a complete message
if((uint32_t) _receiveBuffer.size() < messageSize + 4) return;
// remove header + msg from buffer
const QByteArray& msg = _receiveBuffer.remove(0, messageSize + 4);
// extract message only and remove header + msg from buffer :: QByteArray::remove() does not return the removed data
const QByteArray msg = _receiveBuffer.right(messageSize);
_receiveBuffer.remove(0, messageSize + 4);
const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.mid(3, messageSize).constData());
const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.constData());
flatbuffers::Verifier verifier(msgData, messageSize);
if (flatbuf::VerifyHyperionRequestBuffer(verifier))
@@ -59,7 +58,6 @@ void FlatBufferClient::readyRead()
handleMessage(message);
continue;
}
qDebug()<<"Unable to pasrse msg";
sendErrorReply("Unable to parse message");
}
//emit newMessage(msgData,messageSize);

View File

@@ -7,16 +7,15 @@
// protoserver includes
#include <flatbufserver/FlatBufferConnection.h>
FlatBufferConnection::FlatBufferConnection(const QString & address) :
_socket(),
_skipReply(false),
_prevSocketState(QAbstractSocket::UnconnectedState),
_log(Logger::getInstance("FLATBUFCONNECTION"))
{
FlatBufferConnection::FlatBufferConnection(const QString & address)
: _socket()
, _prevSocketState(QAbstractSocket::UnconnectedState)
, _log(Logger::getInstance("FLATBUFCONNECTION"))
{
QStringList parts = address.split(":");
if (parts.size() != 2)
{
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString());
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse address (%1)").arg(address).toStdString());
}
_host = parts[0];
@@ -24,19 +23,17 @@ FlatBufferConnection::FlatBufferConnection(const QString & address) :
_port = parts[1].toUShort(&ok);
if (!ok)
{
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse the port (%1)").arg(parts[1]).toStdString());
}
// try to connect to host
// init connect
Info(_log, "Connecting to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
connectToHost();
// start the connection timer
_timer.setInterval(5000);
_timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()));
connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData()));
connect(&_timer, &QTimer::timeout, this, &FlatBufferConnection::connectToHost);
_timer.start();
}
@@ -48,48 +45,43 @@ FlatBufferConnection::~FlatBufferConnection()
void FlatBufferConnection::readData()
{
qint64 bytesAvail;
while((bytesAvail = _socket.bytesAvailable()))
_receiveBuffer += _socket.readAll();
// check if we can read a header
while(_receiveBuffer.size() >= 4)
{
// ignore until we get 4 bytes.
if (bytesAvail < 4) {
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if((uint32_t) _receiveBuffer.size() < messageSize + 4) return;
// extract message only and remove header + msg from buffer :: QByteArray::remove() does not return the removed data
const QByteArray msg = _receiveBuffer.right(messageSize);
_receiveBuffer.remove(0, messageSize + 4);
const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.constData());
flatbuffers::Verifier verifier(msgData, messageSize);
if (flatbuf::VerifyHyperionReplyBuffer(verifier))
{
auto message = flatbuf::GetHyperionReply(msgData);
parseReply(message);
continue;
}
char sizeBuf[4];
_socket.read(sizeBuf, sizeof(sizeBuf));
uint32_t messageSize =
((sizeBuf[0]<<24) & 0xFF000000) |
((sizeBuf[1]<<16) & 0x00FF0000) |
((sizeBuf[2]<< 8) & 0x0000FF00) |
((sizeBuf[3] ) & 0x000000FF);
QByteArray buffer;
while((uint32_t)buffer.size() < messageSize)
{
_socket.waitForReadyRead();
buffer.append(_socket.read(messageSize - buffer.size()));
}
const uint8_t* replyData = reinterpret_cast<const uint8_t*>(buffer.constData());
flatbuffers::Verifier verifier(replyData, messageSize);
if (!flatbuf::VerifyHyperionReplyBuffer(verifier))
{
Error(_log, "Error while reading data from host");
return;
}
auto reply = flatbuf::GetHyperionReply(replyData);
parseReply(reply);
Error(_log, "Unable to parse reply");
}
}
void FlatBufferConnection::setSkipReply(bool skip)
void FlatBufferConnection::setSkipReply(const bool& skip)
{
_skipReply = skip;
if(skip)
disconnect(&_socket, &QTcpSocket::readyRead, 0, 0);
else
connect(&_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection);
}
void FlatBufferConnection::setColor(const ColorRgb & color, int priority, int duration)
@@ -191,24 +183,22 @@ bool FlatBufferConnection::parseReply(const flatbuf::HyperionReply *reply)
{
case flatbuf::Type_REPLY:
{
if (!_skipReply)
if (!reply->success())
{
if (!reply->success())
if (flatbuffers::IsFieldPresent(reply, flatbuf::HyperionReply::VT_ERROR))
{
if (flatbuffers::IsFieldPresent(reply, flatbuf::HyperionReply::VT_ERROR))
{
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply->error()->str());
}
else
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply->error()->str());
}
else
{
success = true;
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
}
else
{
success = true;
}
break;
}
case flatbuf::Type_VIDEO:

View File

@@ -6,10 +6,6 @@
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
FlatBufferServer::FlatBufferServer(const QJsonDocument& config, QObject* parent)
: QObject(parent)
, _server(new QTcpServer(this))
@@ -28,7 +24,6 @@ FlatBufferServer::~FlatBufferServer()
void FlatBufferServer::initServer()
{
qDebug()<<"Thread in InitServer is"<<this->thread();
connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection);
// apply config
@@ -37,7 +32,6 @@ void FlatBufferServer::initServer()
void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{
qDebug()<<"Thread in handleSettingsUpdate is"<<this->thread();
if(type == settings::FLATBUFSERVER)
{
const QJsonObject& obj = config.object();
@@ -60,7 +54,6 @@ void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJ
void FlatBufferServer::newConnection()
{
qDebug()<<"Thread in newConnection is"<<this->thread();
while(_server->hasPendingConnections())
{
if(QTcpSocket* socket = _server->nextPendingConnection())

View File

@@ -30,12 +30,19 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
int result = vc_dispmanx_display_get_info(_vc_display, &vc_info);
// Keep compiler happy in 'release' mode
(void)result;
assert(result == 0);
Info(_log, "Display opened with resolution: %dx%d", vc_info.width, vc_info.height);
// Close the displaye
// Close the display
vc_dispmanx_display_close(_vc_display);
if(result != 0)
{
Error(_log, "Failed to open display! Probably no permissions to access the capture interface");
setEnabled(false);
return;
}
else
Info(_log, "Display opened with resolution: %dx%d", vc_info.width, vc_info.height);
// init the resource and capture rectangle
setWidthHeight(width, height);
}
@@ -55,11 +62,12 @@ void DispmanxFrameGrabber::freeResources()
vc_dispmanx_resource_delete(_vc_resource);
}
void DispmanxFrameGrabber::setWidthHeight(int width, int height)
bool DispmanxFrameGrabber::setWidthHeight(int width, int height)
{
if(_width != width || _height != height)
if(Grabber::setWidthHeight(width, height))
{
freeResources();
if(_vc_resource != 0)
vc_dispmanx_resource_delete(_vc_resource);
// Create the resources for capturing image
uint32_t vc_nativeImageHandle;
_vc_resource = vc_dispmanx_resource_create(
@@ -71,7 +79,9 @@ void DispmanxFrameGrabber::setWidthHeight(int width, int height)
// Define the capture rectangle with the same size
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
return true;
}
return false;
}
void DispmanxFrameGrabber::setFlags(const int vc_flags)

View File

@@ -4,7 +4,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
: GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz)
, _grabber(grabWidth, grabHeight)
{
setImageProcessorEnabled(false);
}
void DispmanxWrapper::action()

View File

@@ -82,7 +82,14 @@ void OsxFrameGrabber::setDisplayIndex(int index)
}
image = CGDisplayCreateImage(_display);
assert(image != NULL);
if(image == NULL)
{
Error(_log, "Failed to open main display, disable capture interface");
setEnabled(false);
return;
}
else
setEnabled(true);
Info(_log, "Display opened with resolution: %dx%d@%dbit", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image));

View File

@@ -18,29 +18,29 @@
#include <QDirIterator>
#include <QFileInfo>
#include <QTimer>
#include "grabber/V4L2Grabber.h"
#define CLEAR(x) memset(&(x), 0, sizeof(x))
V4L2Grabber::V4L2Grabber(const QString & device
, int input
, VideoStandard videoStandard
, PixelFormat pixelFormat
, int pixelDecimation
)
: Grabber("V4L2:"+device)
, _deviceName(device)
, _input(input)
, _deviceName()
, _input(-1)
, _videoStandard(videoStandard)
, _ioMethod(IO_METHOD_MMAP)
, _fileDescriptor(-1)
, _buffers()
, _pixelFormat(pixelFormat)
, _pixelDecimation(pixelDecimation)
, _pixelDecimation(-1)
, _lineLength(-1)
, _frameByteSize(-1)
, _noSignalCounterThreshold(50)
, _noSignalCounterThreshold(40)
, _noSignalThresholdColor(ColorRgb{0,0,0})
, _signalDetectionEnabled(true)
, _noSignalDetected(false)
@@ -52,12 +52,17 @@ V4L2Grabber::V4L2Grabber(const QString & device
, _streamNotifier(nullptr)
, _initialized(false)
, _deviceAutoDiscoverEnabled(false)
, _readFrameAdaptTimer(new QTimer(this))
{
//_imageResampler.setHorizontalPixelDecimation(pixelDecimation);
//_imageResampler.setVerticalPixelDecimation(pixelDecimation);
// setup stream notify locker with 10hz
connect(_readFrameAdaptTimer, &QTimer::timeout, this, &V4L2Grabber::unlockReadFrame);
_readFrameAdaptTimer->setInterval(100);
setPixelDecimation(pixelDecimation);
getV4Ldevices();
// init
setDeviceVideoStandard(device, videoStandard);
}
V4L2Grabber::~V4L2Grabber()
@@ -67,10 +72,12 @@ V4L2Grabber::~V4L2Grabber()
void V4L2Grabber::uninit()
{
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
// stop if the grabber was not stopped
if (_initialized)
{
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
_readFrameAdaptTimer->stop();
stop();
uninit_device();
close_device();
@@ -78,7 +85,6 @@ void V4L2Grabber::uninit()
}
}
bool V4L2Grabber::init()
{
if (! _initialized)
@@ -133,10 +139,15 @@ bool V4L2Grabber::init()
bool opened = false;
try
{
open_device();
opened = true;
init_device(_videoStandard, _input);
_initialized = true;
// do not init with unknown device
if(_deviceName != "unknown")
{
open_device();
opened = true;
init_device(_videoStandard, _input);
_initialized = true;
_readFrameAdaptTimer->start();
}
}
catch(std::exception& e)
{
@@ -529,13 +540,13 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
break;
}
// TODO Does never accept own sizes? use always _imageResampler instead
/*
// calc the size based on pixelDecimation
fmt.fmt.pix.width = fmt.fmt.pix.width / _pixelDecimation;
fmt.fmt.pix.height = fmt.fmt.pix.height / _pixelDecimation;
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// set the settings
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
{
@@ -550,6 +561,9 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
throw_errno_exception("VIDIOC_G_FMT");
return;
}
*/
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// store width & height
_width = fmt.fmt.pix.width;
@@ -701,6 +715,10 @@ void V4L2Grabber::stop_capturing()
int V4L2Grabber::read_frame()
{
// read_frame() is called with 25Hz, adapt to 10Hz. In the end it's up to the stream notifier if we get calls or not
if(!_readFrame) return -1;
_readFrame = false;
bool rc = false;
try
@@ -933,18 +951,30 @@ void V4L2Grabber::setPixelDecimation(int pixelDecimation)
{
if(_pixelDecimation != pixelDecimation)
{
_pixelDecimation = pixelDecimation;
uninit();
init();
// start if init is a success
if(init())
start();
_imageResampler.setHorizontalPixelDecimation(pixelDecimation);
_imageResampler.setVerticalPixelDecimation(pixelDecimation);
}
}
void V4L2Grabber::setInputVideoStandard(int input, VideoStandard videoStandard)
void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStandard)
{
if(_input != input || _videoStandard != videoStandard)
if(_deviceName != device || _videoStandard != videoStandard)
{
_input = input;
_videoStandard = videoStandard;
// extract input of device
QChar input = device.at(device.size() - 1);
_input = input.isNumber() ? input.digitValue() : -1;
uninit();
init();
_deviceName = device;
_videoStandard = videoStandard;
// start if init is a success
if(init())
start();
}
}

View File

@@ -6,13 +6,11 @@
#include <QTimer>
V4L2Wrapper::V4L2Wrapper(const QString &device,
int input,
VideoStandard videoStandard,
PixelFormat pixelFormat,
int pixelDecimation )
: GrabberWrapper("V4L2:"+device, &_grabber, 0, 0, 10)
, _grabber(device,
input,
videoStandard,
pixelFormat,
pixelDecimation)
@@ -66,7 +64,7 @@ void V4L2Wrapper::readError(const char* err)
void V4L2Wrapper::action()
{
// dummy as v4l get notifications from stream
}
void V4L2Wrapper::setSignalDetectionEnable(bool enable)

View File

@@ -110,6 +110,7 @@ bool X11Grabber::Setup()
bool result = (updateScreenDimensions(true) >=0);
ErrorIf(!result, _log, "X11 Grabber start failed");
setEnabled(result);
return result;
}
@@ -278,11 +279,6 @@ void X11Grabber::setVideoMode(VideoMode mode)
updateScreenDimensions(true);
}
void X11Grabber::setWidthHeight(int width, int height)
{
// empty overwrite
}
void X11Grabber::setPixelDecimation(int pixelDecimation)
{
if(_pixelDecimation != pixelDecimation)

View File

@@ -17,6 +17,7 @@ target_link_libraries(hyperion
hyperion-utils
leddevice
bonjour
boblightserver
effectengine
${QT_LIBRARIES}
)

View File

@@ -1,12 +1,14 @@
#include <hyperion/CaptureCont.h>
#include <hyperion/Hyperion.h>
#include <QTimer>
CaptureCont::CaptureCont(Hyperion* hyperion)
: QObject()
, _hyperion(hyperion)
, _systemCaptEnabled(false)
, _v4lCaptEnabled(false)
, _v4lInactiveTimer(new QTimer(this))
{
// settings changes
connect(_hyperion, &Hyperion::settingsChanged, this, &CaptureCont::handleSettingsUpdate);
@@ -14,6 +16,11 @@ CaptureCont::CaptureCont(Hyperion* hyperion)
// comp changes
connect(_hyperion, &Hyperion::componentStateChanged, this, &CaptureCont::componentStateChanged);
// inactive timer v4l
connect(_v4lInactiveTimer, &QTimer::timeout, this, &CaptureCont::setV4lInactive);
_v4lInactiveTimer->setSingleShot(true);
_v4lInactiveTimer->setInterval(1000);
// init
handleSettingsUpdate(settings::INSTCAPTURE, _hyperion->getSetting(settings::INSTCAPTURE));
}
@@ -25,6 +32,7 @@ CaptureCont::~CaptureCont()
void CaptureCont::handleV4lImage(const Image<ColorRgb> & image)
{
_v4lInactiveTimer->start();
_hyperion->setInputImage(_v4lCaptPrio, image);
}
@@ -40,7 +48,7 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable)
{
if(enable)
{
_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER, "System", "DoNotKnow");
_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER);
connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage);
}
else
@@ -59,13 +67,14 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable)
{
if(enable)
{
_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L, "System", "DoNotKnow");
_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L);
connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
}
else
{
disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
_hyperion->clear(_v4lCaptPrio);
_v4lInactiveTimer->stop();
}
_v4lCaptEnabled = enable;
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_V4L, enable);
@@ -104,3 +113,8 @@ void CaptureCont::componentStateChanged(const hyperion::Components component, bo
setV4LCaptureEnable(enable);
}
}
void CaptureCont::setV4lInactive()
{
_hyperion->setInputInactive(_v4lCaptPrio);
}

View File

@@ -55,9 +55,9 @@ bool ComponentRegister::setHyperionEnable(const bool& state)
return false;
}
bool ComponentRegister::isComponentEnabled(const hyperion::Components& comp) const
int ComponentRegister::isComponentEnabled(const hyperion::Components& comp) const
{
return _componentStates.at(comp);
return (_componentStates.count(comp)) ? _componentStates.at(comp) : -1;
}
void ComponentRegister::componentStateChanged(const hyperion::Components comp, const bool activated)

View File

@@ -24,12 +24,13 @@ Grabber::~Grabber()
void Grabber::setEnabled(bool enable)
{
Info(_log,"Capture interface is now %s", enable ? "enabled" : "disabled");
_enabled = enable;
}
void Grabber::setVideoMode(VideoMode mode)
{
Debug(_log,"setvideomode %d", mode);
Debug(_log,"Set videomode to %d", mode);
_videoMode = mode;
if ( _useImageResampler )
{
@@ -68,18 +69,20 @@ void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTo
}
}
void Grabber::setWidthHeight(int width, int height)
bool Grabber::setWidthHeight(int width, int height)
{
// eval changes with crop
if (width>0 && height>0)
if ( (width>0 && height>0) && (_width != width || _height != height) )
{
if (_cropLeft + _cropRight >= width || _cropTop + _cropBottom >= height)
{
Error(_log, "Rejecting invalid width/height values as it collides with image cropping: width: %d, height: %d", width, height);
return;
return false;
}
Debug(_log, "Set new width: %d, height: %d for capture", width, height);
_width = width;
_height = height;
return true;
}
return false;
}

View File

@@ -3,19 +3,14 @@
#include <hyperion/Grabber.h>
#include <HyperionConfig.h>
//forwarder
#include <hyperion/MessageForwarder.h>
// qt
#include <QTimer>
GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz)
: _grabberName(grabberName)
, _hyperion(Hyperion::getInstance())
, _timer(new QTimer(this))
, _updateInterval_ms(1000/updateRate_Hz)
, _log(Logger::getInstance(grabberName))
, _forward(true)
, _ggrabber(ggrabber)
, _image(0,0)
{
@@ -24,8 +19,6 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned
_image.resize(width, height);
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action);
}
@@ -105,7 +98,7 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
else
obj = config.object();
if(type == settings::SYSTEMCAPTURE)
if(type == settings::SYSTEMCAPTURE && !_grabberName.startsWith("V4L"))
{
// width/height
_ggrabber->setWidthHeight(obj["width"].toInt(96), obj["height"].toInt(96));
@@ -138,7 +131,8 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
}
}
if(type == settings::V4L2)
// v4l instances only!
if(type == settings::V4L2 && _grabberName.startsWith("V4L"))
{
// pixel decimation for v4l
_ggrabber->setPixelDecimation(obj["sizeDecimation"].toInt(8));
@@ -160,8 +154,8 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
obj["redSignalThreshold"].toDouble(0.0)/100.0,
obj["greenSignalThreshold"].toDouble(0.0)/100.0,
obj["blueSignalThreshold"].toDouble(0.0)/100.0);
_ggrabber->setInputVideoStandard(
obj["input"].toInt(0),
_ggrabber->setDeviceVideoStandard(
obj["device"].toString("auto"),
parseVideoStandard(obj["standard"].toString("no-change")));
}

View File

@@ -47,6 +47,9 @@
// CaptureControl (Daemon capture)
#include <hyperion/CaptureCont.h>
// Boblight
#include <boblightserver/BoblightServer.h>
Hyperion* Hyperion::_hyperion = nullptr;
Hyperion* Hyperion::initInstance( HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath)
@@ -122,7 +125,7 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
const QJsonObject color = getSetting(settings::COLOR).object();
// initialize leddevices
const QJsonObject ledDevice = getSetting(settings::DEVICE).object();
QJsonObject ledDevice = getSetting(settings::DEVICE).object();
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
_device = LedDeviceFactory::construct(ledDevice);
@@ -159,6 +162,11 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
// if there is no startup / background eff and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a prioritiy change)
update();
// boblight, can't live in global scope as it depends on layout
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
}
Hyperion::~Hyperion()
@@ -178,6 +186,7 @@ void Hyperion::freeObjects(bool emitCloseSignal)
}
// delete components on exit of hyperion core
delete _boblightServer;
delete _captureCont;
delete _effectEngine;
//delete _deviceSmooth;
@@ -249,7 +258,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
else if(type == settings::DEVICE)
{
_lockUpdate = true;
const QJsonObject dev = config.object();
QJsonObject dev = config.object();
// handle hwLedCount update
_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount());
@@ -281,7 +290,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
_deviceSmooth->startTimerDelayed();
_lockUpdate = false;
}
// update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer
// update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer color
update();
}
@@ -421,6 +430,11 @@ const bool Hyperion::setInputImage(const int priority, const Image<ColorRgb>& im
return false;
}
const bool Hyperion::setInputInactive(const quint8& priority)
{
return _muxer.setInputInactive(priority);
}
void Hyperion::setColor(int priority, const ColorRgb &color, const int timeout_ms, const QString& origin, bool clearEffects)
{
// clear effect if this call does not come from an effect
@@ -602,7 +616,7 @@ void Hyperion::update()
// disable the black border detector for effects and ledmapping to 0
if(compChanged)
{
_imageProcessor->setBlackbarDetectDisable((_prevCompId == hyperion::COMP_EFFECT || _prevCompId == hyperion::COMP_GRABBER));
_imageProcessor->setBlackbarDetectDisable((_prevCompId == hyperion::COMP_EFFECT));
_imageProcessor->setHardLedMappingType((_prevCompId == hyperion::COMP_EFFECT) ? 0 : -1);
}
_imageProcessor->process(image, _ledBuffer);

View File

@@ -228,7 +228,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
}
_currentConfigId = cfg;
//DebugIf( enabled() && !_pause, _log, "set smoothing cfg: %d, interval: %d ms, settlingTime: %d ms, updateDelay: %d frames", _currentConfigId, _updateInterval, _settlingTime, _outputDelay );
InfoIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId );
DebugIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId );
return true;
}

View File

@@ -240,6 +240,12 @@ const bool PriorityMuxer::setInputImage(const int priority, const Image<ColorRgb
return true;
}
const bool PriorityMuxer::setInputInactive(const quint8& priority)
{
Image<ColorRgb> image;
return setInputImage(priority, image, -100);
}
const bool PriorityMuxer::clearInput(const uint8_t priority)
{
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))

View File

@@ -133,8 +133,6 @@ SettingsManager::~SettingsManager()
const QJsonDocument SettingsManager::getSetting(const settings::type& type)
{
//return _sTable->getSettingsRecord(settings::typeToString(type));
QString key = settings::typeToString(type);
if(_qconfig[key].isObject())
return QJsonDocument(_qconfig[key].toObject());
@@ -168,6 +166,23 @@ const bool SettingsManager::saveSettings(QJsonObject config, const bool& correct
return false;
}
// compare old data with new data to emit/save changes accordingly
for(const auto key : config.keys())
{
QString newData, oldData;
_qconfig[key].isObject()
? oldData = QString(QJsonDocument(_qconfig[key].toObject()).toJson(QJsonDocument::Compact))
: oldData = QString(QJsonDocument(_qconfig[key].toArray()).toJson(QJsonDocument::Compact));
config[key].isObject()
? newData = QString(QJsonDocument(config[key].toObject()).toJson(QJsonDocument::Compact))
: newData = QString(QJsonDocument(config[key].toArray()).toJson(QJsonDocument::Compact));
if(oldData != newData)
emit settingsChanged(settings::stringToType(key), QJsonDocument::fromJson(newData.toLocal8Bit()));
}
// store the current state
_qconfig = config;

View File

@@ -55,6 +55,10 @@
{
"$ref": "schema-protoServer.json"
},
"flatbufServer":
{
"$ref": "schema-flatbufServer.json"
},
"boblightServer" :
{
"$ref": "schema-boblightServer.json"

View File

@@ -16,6 +16,7 @@
<file alias="schema-forwarder.json">schema/schema-forwarder.json</file>
<file alias="schema-jsonServer.json">schema/schema-jsonServer.json</file>
<file alias="schema-protoServer.json">schema/schema-protoServer.json</file>
<file alias="schema-flatbufServer.json">schema/schema-flatbufServer.json</file>
<file alias="schema-boblightServer.json">schema/schema-boblightServer.json</file>
<file alias="schema-udpListener.json">schema/schema-udpListener.json</file>
<file alias="schema-webConfig.json">schema/schema-webConfig.json</file>

View File

@@ -2,18 +2,21 @@
"type" : "object",
"title" : "edt_dev_general_heading_title",
"required" : true,
"defaultProperties": ["ledCount","colorOrder","rewriteTime","minimumWriteTime"],
"defaultProperties": ["hardwareLedCount","colorOrder","rewriteTime"],
"properties" :
{
"type" :
{
"type" : "string"
"type" : "string",
"propertyOrder" : 1
},
"ledCount" :
"hardwareLedCount" :
{
"type" : "integer",
"minimum" : 0,
"title" : "edt_dev_general_ledCount_title",
"title" : "edt_dev_general_hardwareLedCount_title",
"minimum" : 1,
"default" : 1,
"access" : "expert",
"propertyOrder" : 2
},
"colorOrder" :

View File

@@ -3,7 +3,7 @@
"required" : true,
"title" : "edt_conf_v4l2_heading_title",
"minItems": 1,
"maxItems": 2,
"maxItems": 1,
"items":
{
"type" : "object",
@@ -16,17 +16,9 @@
"type" : "string",
"title" : "edt_conf_v4l2_device_title",
"default" : "auto",
"minLength" : 4,
"required" : true,
"propertyOrder" : 2
},
"input" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_input_title",
"minimum" : 0,
"default" : 0,
"required" : true,
"propertyOrder" : 3
"propertyOrder" : 1
},
"standard" :
{
@@ -38,7 +30,7 @@
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
},
"required" : true,
"propertyOrder" : 4
"propertyOrder" : 2
},
"sizeDecimation" :
{
@@ -48,7 +40,7 @@
"maximum" : 30,
"default" : 6,
"required" : true,
"propertyOrder" : 8
"propertyOrder" : 3
},
"cropLeft" :
{
@@ -58,7 +50,7 @@
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 11
"propertyOrder" : 4
},
"cropRight" :
{
@@ -68,7 +60,7 @@
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 12
"propertyOrder" : 5
},
"cropTop" :
{
@@ -78,7 +70,7 @@
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 13
"propertyOrder" : 6
},
"cropBottom" :
{
@@ -88,7 +80,7 @@
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 14
"propertyOrder" : 7
},
"signalDetection" :
{
@@ -96,7 +88,7 @@
"title" : "edt_conf_v4l2_signalDetection_title",
"default" : false,
"required" : true,
"propertyOrder" : 15
"propertyOrder" : 8
},
"redSignalThreshold" :
{
@@ -112,7 +104,7 @@
}
},
"required" : true,
"propertyOrder" : 16
"propertyOrder" : 9
},
"greenSignalThreshold" :
{
@@ -128,7 +120,7 @@
}
},
"required" : true,
"propertyOrder" : 17
"propertyOrder" : 10
},
"blueSignalThreshold" :
{
@@ -144,7 +136,7 @@
}
},
"required" : true,
"propertyOrder" : 18
"propertyOrder" : 11
},
"sDVOffsetMin" :
{
@@ -160,7 +152,7 @@
}
},
"required" : true,
"propertyOrder" : 19
"propertyOrder" : 12
},
"sDVOffsetMax" :
{
@@ -176,7 +168,7 @@
}
},
"required" : true,
"propertyOrder" : 20
"propertyOrder" : 13
},
"sDHOffsetMin" :
{
@@ -192,7 +184,7 @@
}
},
"required" : true,
"propertyOrder" : 21
"propertyOrder" : 14
},
"sDHOffsetMax" :
{
@@ -208,7 +200,7 @@
}
},
"required" : true,
"propertyOrder" : 22
"propertyOrder" : 15
}
},
"additionalProperties" : false

View File

@@ -8,7 +8,7 @@
{
"type" : "boolean",
"required" : true,
"title" : "edt_conf_instC_systemEnable",
"title" : "edt_conf_instC_systemEnable_title",
"default" : true,
"propertyOrder" : 1
},
@@ -26,7 +26,7 @@
{
"type" : "boolean",
"required" : true,
"title" : "edt_conf_instC_v4lEnable",
"title" : "edt_conf_instC_v4lEnable_title",
"default" : false,
"propertyOrder" : 3
},

View File

@@ -3,14 +3,6 @@
"title" : "edt_conf_webc_heading_title",
"properties" :
{
"enable" :
{
"type" : "boolean",
"title" : "edt_conf_general_enable_title",
"default" : true,
"access" : "expert",
"propertyOrder" : 1
},
"document_root" :
{
"type" : "string",

View File

@@ -5,11 +5,8 @@
#include <jsonserver/JsonServer.h>
#include "JsonClientConnection.h"
// hyperion include
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
// bonjour include
#include <bonjour/bonjourserviceregister.h>
#include <hyperion/ComponentRegister.h>
// qt includes
#include <QTcpServer>
@@ -20,27 +17,16 @@
JsonServer::JsonServer(const QJsonDocument& config)
: QObject()
, _server(new QTcpServer(this))
, _hyperion(Hyperion::getInstance())
, _openConnections()
, _log(Logger::getInstance("JSONSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{
Debug(_log, "Created instance");
// Set trigger for incoming connections
connect(_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
// receive state of forwarder
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonServer::componentStateChanged);
// listen for component register changes
connect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
// init
handleSettingsUpdate(settings::JSONSERVER, config);
// set initial state of forwarding
componentStateChanged(hyperion::COMP_FORWARDER, _componentRegister->isComponentEnabled(hyperion::COMP_FORWARDER));
}
JsonServer::~JsonServer()
@@ -64,7 +50,13 @@ void JsonServer::start()
if(_serviceRegister == nullptr)
{
_serviceRegister = new BonjourServiceRegister();
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-json._tcp", _port);
}
else if( _serviceRegister->getPort() != _port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-json._tcp", _port);
}
}
@@ -123,38 +115,6 @@ void JsonServer::closedConnection(void)
connection->deleteLater();
}
void JsonServer::componentStateChanged(const hyperion::Components component, bool enable)
{
if (component == hyperion::COMP_FORWARDER)
{
if(enable)
{
connect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
}
else
{
disconnect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
}
}
}
void JsonServer::forwardJsonMessage(const QJsonObject &message)
{
QTcpSocket client;
QStringList list = _hyperion->getForwarder()->getJsonSlaves();
for (const auto& entry : list)
{
QStringList splitted = entry.split(":");
client.connectToHost(splitted[0], splitted[1].toInt());
if ( client.waitForConnected(500) )
{
sendMessage(message,&client);
client.close();
}
}
}
void JsonServer::sendMessage(const QJsonObject & message, QTcpSocket * socket)
{
// serialize message

View File

@@ -16,6 +16,9 @@
// hyperion util includes
#include "utils/ColorRgb.h"
// Hyperion includes
#include <hyperion/Hyperion.h>
// project includes
#include "ProtoClientConnection.h"
@@ -198,7 +201,7 @@ void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &messag
int priority = message.priority();
// clear priority
_hyperion->clear(priority);
//_hyperion->clear(priority);
// send reply
sendSuccessReply();
}
@@ -206,7 +209,7 @@ void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &messag
void ProtoClientConnection::handleClearallCommand()
{
// clear priority
_hyperion->clearall();
//_hyperion->clearall();
// send reply
sendSuccessReply();

View File

@@ -9,9 +9,6 @@
#include <QStringList>
#include <QString>
// Hyperion includes
#include <hyperion/Hyperion.h>
//Utils includes
#include <utils/VideoMode.h>
@@ -19,6 +16,8 @@
#include "message.pb.h"
#include "protoserver/ProtoConnection.h"
class Hyperion;
///
/// The Connection object created by a ProtoServer when a new connection is establshed
///

View File

@@ -3,10 +3,9 @@
// qt incl
#include <QTcpServer>
#include <QJsonObject>
// project includes
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
#include <protoserver/ProtoServer.h>
#include "protoserver/ProtoConnection.h"
#include "ProtoClientConnection.h"
@@ -15,30 +14,13 @@
ProtoServer::ProtoServer(const QJsonDocument& config)
: QObject()
, _hyperion(Hyperion::getInstance())
, _server(new QTcpServer(this))
, _openConnections()
, _log(Logger::getInstance("PROTOSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{
Debug(_log,"Instance created");
connect( _server, SIGNAL(newConnection()), this, SLOT(newConnection()));
handleSettingsUpdate(settings::PROTOSERVER, config);
QStringList slaves = _hyperion->getForwarder()->getProtoSlaves();
for (const auto& entry : slaves)
{
ProtoConnection* p = new ProtoConnection(entry.toLocal8Bit().constData());
p->setSkipReply(true);
_proxy_connections << p;
}
// listen for component changes
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &ProtoServer::componentStateChanged);
// get inital forwarder state
componentStateChanged(hyperion::COMP_FORWARDER, _componentRegister->isComponentEnabled(hyperion::COMP_FORWARDER));
}
ProtoServer::~ProtoServer()
@@ -46,9 +28,6 @@ ProtoServer::~ProtoServer()
foreach (ProtoClientConnection * connection, _openConnections) {
delete connection;
}
while (!_proxy_connections.isEmpty())
delete _proxy_connections.takeFirst();
}
void ProtoServer::start()
@@ -65,7 +44,13 @@ void ProtoServer::start()
if(_serviceRegister == nullptr)
{
_serviceRegister = new BonjourServiceRegister();
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port);
}
else if( _serviceRegister->getPort() != _port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port);
}
}
@@ -110,37 +95,11 @@ void ProtoServer::newConnection()
// register slot for cleaning up after the connection closed
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
// register forward signal for video mode
connect(this, SIGNAL(videoMode(VideoMode)), connection, SLOT(setVideoMode(VideoMode)));
//connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
}
}
}
void ProtoServer::newMessage(const proto::HyperionRequest * message)
{
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->sendMessage(*message);
}
void ProtoServer::sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms)
{
if ( _forwarder_enabled )
{
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->setImage(image, priority, duration_ms);
}
}
void ProtoServer::componentStateChanged(const hyperion::Components component, bool enable)
{
if (component == hyperion::COMP_FORWARDER)
{
_forwarder_enabled = enable;
}
}
void ProtoServer::closedConnection(ProtoClientConnection *connection)
{
Debug(_log, "Connection closed");

View File

@@ -1,4 +1,4 @@
find_package(PythonLibs 3.4 REQUIRED)
find_package(PythonLibs 3.5 REQUIRED)
# Include the python directory. Also include the parent (which is for example /usr/include)
# which may be required when it is not includes by the (cross-) compiler by default.

View File

@@ -1,24 +1,21 @@
// project includes
#include <udplistener/UDPListener.h>
// hyperion includes
#include <hyperion/Hyperion.h>
// bonjour includes
#include <bonjour/bonjourserviceregister.h>
// hyperion util includes
#include "utils/ColorRgb.h"
// hyperion includes
#include "HyperionConfig.h"
// qt includes
#include <QUdpSocket>
#include <QJsonObject>
using namespace hyperion;
UDPListener::UDPListener(const QJsonDocument& config) :
QObject(),
_hyperion(Hyperion::getInstance()),
_server(new QUdpSocket(this)),
_openConnections(),
_priority(0),
_timeout(0),
_log(Logger::getInstance("UDPLISTENER")),
@@ -26,10 +23,6 @@ UDPListener::UDPListener(const QJsonDocument& config) :
_listenPort(0)
{
Debug(_log, "Instance created");
// listen for comp changes
connect(_hyperion, SIGNAL(componentStateChanged(hyperion::Components,bool)), this, SLOT(componentStateChanged(hyperion::Components,bool)));
// Set trigger for incoming connections
connect(_server, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
// init
handleSettingsUpdate(settings::UDPLISTENER, config);
@@ -40,7 +33,6 @@ UDPListener::~UDPListener()
// clear the current channel
stop();
delete _server;
_hyperion->clear(_priority);
}
@@ -67,12 +59,17 @@ void UDPListener::start()
WarningIf( ! joinGroupOK, _log, "Multicast failed");
}
_isActive = true;
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
if(_bonjourService == nullptr)
if(_serviceRegister == nullptr)
{
_bonjourService = new BonjourServiceRegister();
_bonjourService->registerService("_hyperiond-udp._udp", _listenPort);
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-udp._udp", _listenPort);
}
else if( _serviceRegister->getPort() != _listenPort)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-udp._udp", _listenPort);
}
}
}
@@ -85,8 +82,7 @@ void UDPListener::stop()
_server->close();
_isActive = false;
Info(_log, "Stopped");
_hyperion->clear(_priority);
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
emit clearGlobalPriority(_priority, hyperion::COMP_UDPLISTENER);
}
void UDPListener::componentStateChanged(const hyperion::Components component, bool enable)
@@ -124,20 +120,19 @@ void UDPListener::readPendingDatagrams()
void UDPListener::processTheDatagram(const QByteArray * datagram, const QHostAddress * sender)
{
int packetLedCount = datagram->size()/3;
int hyperionLedCount = Hyperion::getInstance()->getLedCount();
DebugIf( (packetLedCount != hyperionLedCount), _log, "packetLedCount (%d) != hyperionLedCount (%d)", packetLedCount, hyperionLedCount);
//DebugIf( (packetLedCount != hyperionLedCount), _log, "packetLedCount (%d) != hyperionLedCount (%d)", packetLedCount, hyperionLedCount);
std::vector<ColorRgb> _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK);
std::vector<ColorRgb> _ledColors(packetLedCount, ColorRgb::BLACK);
for (int ledIndex=0; ledIndex < qMin(packetLedCount, hyperionLedCount); ledIndex++) {
for (int ledIndex=0; ledIndex < packetLedCount; ledIndex++) {
ColorRgb & rgb = _ledColors[ledIndex];
rgb.red = datagram->at(ledIndex*3+0);
rgb.green = datagram->at(ledIndex*3+1);
rgb.blue = datagram->at(ledIndex*3+2);
}
// TODO provide a setInput with origin arg to overwrite senders smarter
_hyperion->registerInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString()));
_hyperion->setInput(_priority, _ledColors, _timeout);
emit registerGlobalInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString()));
emit setGlobalInput(_priority, _ledColors, _timeout);
}
void UDPListener::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)

View File

@@ -13,11 +13,15 @@
#include <QDir>
#include <QDateTime>
Stats::Stats()
Stats* Stats::instance = nullptr;
Stats::Stats(const QJsonObject& config)
: QObject()
, _log(Logger::getInstance("STATS"))
, _hyperion(Hyperion::getInstance())
{
Stats::instance = this;
// generate hash
foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
{
@@ -38,8 +42,31 @@ Stats::Stats()
return;
}
// prep data
handleDataUpdate(config);
// QNetworkRequest Header
_req.setRawHeader("Content-Type", "application/json");
_req.setRawHeader("Authorization", "Basic SHlwZXJpb25YbDQ5MlZrcXA6ZDQxZDhjZDk4ZjAwYjIw");
connect(&_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(resolveReply(QNetworkReply*)));
// 7 days interval
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendHTTP()));
timer->start(604800000);
// delay initial check
QTimer::singleShot(60000, this, SLOT(initialExec()));
}
Stats::~Stats()
{
}
void Stats::handleDataUpdate(const QJsonObject& config)
{
// prepare content
QJsonObject config = _hyperion->getQJsonConfig();
SysInfo::HyperionSysInfo data = SysInfo::get();
QJsonObject system;
@@ -63,25 +90,6 @@ Stats::Stats()
QJsonDocument doc(system);
_ba = doc.toJson();
// QNetworkRequest Header
_req.setRawHeader("Content-Type", "application/json");
_req.setRawHeader("Authorization", "Basic SHlwZXJpb25YbDQ5MlZrcXA6ZDQxZDhjZDk4ZjAwYjIw");
connect(&_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(resolveReply(QNetworkReply*)));
// 7 days interval
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendHTTP()));
timer->start(604800000);
//delay initial check
QTimer::singleShot(60000, this, SLOT(initialExec()));
}
Stats::~Stats()
{
}
void Stats::initialExec()

View File

@@ -13,11 +13,9 @@
#include <utils/Process.h>
#include <utils/jsonschema/QJsonFactory.h>
CgiHandler::CgiHandler (Hyperion * hyperion, QObject * parent)
CgiHandler::CgiHandler (QObject * parent)
: QObject(parent)
, _hyperion(hyperion)
, _args(QStringList())
, _hyperionConfig(_hyperion->getQJsonConfig())
, _baseUrl()
, _log(Logger::getInstance("WEBSERVER"))
{
@@ -57,11 +55,6 @@ void CgiHandler::cmd_cfg_jsonserver()
if ( _args.at(0) == "cfg_jsonserver" )
{
quint16 jsonPort = 19444;
if (_hyperionConfig.contains("jsonServer"))
{
const QJsonObject jsonConfig = _hyperionConfig["jsonServer"].toObject();
jsonPort = jsonConfig["port"].toInt(jsonPort);
}
// send result as reply
_reply->addHeader ("Content-Type", "text/plain" );

View File

@@ -5,7 +5,6 @@
#include <QString>
#include <QStringList>
#include <hyperion/Hyperion.h>
#include <utils/Logger.h>
#include "QtHttpReply.h"
@@ -15,7 +14,7 @@ class CgiHandler : public QObject {
Q_OBJECT
public:
CgiHandler (Hyperion * hyperion, QObject * parent = NULL);
CgiHandler (QObject * parent = NULL);
virtual ~CgiHandler (void);
void setBaseUrl(const QString& url);
@@ -26,11 +25,9 @@ public:
void cmd_runscript ();
private:
Hyperion* _hyperion;
QtHttpReply * _reply;
QtHttpRequest * _request;
QStringList _args;
const QJsonObject & _hyperionConfig;
QString _baseUrl;
Logger * _log;
};

View File

@@ -19,67 +19,69 @@ class QtHttpReply;
class QtHttpClientWrapper;
class QtHttpServerWrapper : public QTcpServer {
Q_OBJECT
Q_OBJECT
public:
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
virtual ~QtHttpServerWrapper (void);
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
virtual ~QtHttpServerWrapper (void);
void setUseSecure (const bool ssl = true);
void setUseSecure (const bool ssl = true);
protected:
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
private:
bool m_useSsl;
bool m_useSsl;
};
class QtHttpServer : public QObject {
Q_OBJECT
Q_OBJECT
public:
explicit QtHttpServer (QObject * parent = Q_NULLPTR);
explicit QtHttpServer (QObject * parent = Q_NULLPTR);
static const QString & HTTP_VERSION;
static const QString & HTTP_VERSION;
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
const QString & getServerName (void) const;
const QString & getServerName (void) const;
quint16 getServerPort (void) const;
QString getErrorString (void) const;
quint16 getServerPort (void) const;
QString getErrorString (void) const;
// const bool isListening(void) { return m_sockServer->isListening(); };
public slots:
void start (quint16 port = 0);
void stop (void);
void setServerName (const QString & serverName);
void setUseSecure (const bool ssl = true);
void setPrivateKey (const QSslKey & key);
void setCertificates (const QList<QSslCertificate> & certs);
void start (quint16 port = 0);
void stop (void);
void setServerName (const QString & serverName);
void setUseSecure (const bool ssl = true);
void setPrivateKey (const QSslKey & key);
void setCertificates (const QList<QSslCertificate> & certs);
signals:
void started (quint16 port);
void stopped (void);
void error (const QString & msg);
void clientConnected (const QString & guid);
void clientDisconnected (const QString & guid);
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
void started (quint16 port);
void stopped (void);
void error (const QString & msg);
void clientConnected (const QString & guid);
void clientDisconnected (const QString & guid);
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private slots:
void onClientConnected (void);
void onClientDisconnected (void);
void onClientSslEncrypted (void);
void onClientSslPeerVerifyError (const QSslError & err);
void onClientSslErrors (const QList<QSslError> & errors);
void onClientSslModeChanged (QSslSocket::SslMode mode);
void onClientConnected (void);
void onClientDisconnected (void);
void onClientSslEncrypted (void);
void onClientSslPeerVerifyError (const QSslError & err);
void onClientSslErrors (const QList<QSslError> & errors);
void onClientSslModeChanged (QSslSocket::SslMode mode);
private:
bool m_useSsl;
QSslKey m_sslKey;
QList<QSslCertificate> m_sslCerts;
QString m_serverName;
QtHttpServerWrapper * m_sockServer;
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
bool m_useSsl;
QSslKey m_sslKey;
QList<QSslCertificate> m_sslCerts;
QString m_serverName;
QtHttpServerWrapper * m_sockServer;
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
};
#endif // QTHTTPSERVER_H

View File

@@ -10,11 +10,10 @@
#include <QResource>
#include <exception>
StaticFileServing::StaticFileServing (Hyperion *hyperion, QObject * parent)
StaticFileServing::StaticFileServing (QObject * parent)
: QObject (parent)
, _hyperion(hyperion)
, _baseUrl ()
, _cgi(hyperion, this)
, _cgi(this)
, _log(Logger::getInstance("WEBSERVER"))
{
Q_INIT_RESOURCE(WebConfig);

View File

@@ -1,22 +1,23 @@
#ifndef STATICFILESERVING_H
#define STATICFILESERVING_H
#include <QMimeDatabase>
// locales includes
#include "CgiHandler.h"
//#include "QtHttpServer.h"
// qt includes
#include <QMimeDatabase>
#include "QtHttpRequest.h"
#include "QtHttpReply.h"
#include "QtHttpHeader.h"
#include "CgiHandler.h"
#include <hyperion/Hyperion.h>
//utils includes
#include <utils/Logger.h>
class StaticFileServing : public QObject {
Q_OBJECT
public:
explicit StaticFileServing (Hyperion *hyperion, QObject * parent = nullptr);
explicit StaticFileServing (QObject * parent = nullptr);
virtual ~StaticFileServing (void);
void setBaseUrl(const QString& url);
@@ -25,7 +26,6 @@ public slots:
void onRequestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private:
Hyperion * _hyperion;
QString _baseUrl;
QMimeDatabase * _mimeDb;
CgiHandler _cgi;

View File

@@ -1,7 +1,11 @@
#pragma once
// utils includes
#include <utils/Logger.h>
// qt includes
#include <QJsonObject>
class QtHttpServer;
class QtHttpRequest;
class QtHttpClientWrapper;

View File

@@ -1,17 +1,21 @@
#include "webserver/WebServer.h"
#include "StaticFileServing.h"
#include "QtHttpServer.h"
// bonjour
// qt includes
#include "QtHttpServer.h"
#include <QFileInfo>
#include <QJsonObject>
// bonjour includes
#include <bonjour/bonjourserviceregister.h>
#include <bonjour/bonjourrecord.h>
#include <QFileInfo>
// utils includes
#include <utils/NetUtils.h>
WebServer::WebServer(const QJsonDocument& config, QObject * parent)
: QObject(parent)
, _log(Logger::getInstance("WEBSERVER"))
, _hyperion(Hyperion::getInstance())
, _server(new QtHttpServer (this))
{
_server->setServerName (QStringLiteral ("Hyperion Webserver"));
@@ -21,7 +25,7 @@ WebServer::WebServer(const QJsonDocument& config, QObject * parent)
connect (_server, &QtHttpServer::error, this, &WebServer::onServerError);
// create StaticFileServing
_staticFileServing = new StaticFileServing (_hyperion, this);
_staticFileServing = new StaticFileServing (this);
connect(_server, &QtHttpServer::requestNeedsReply, _staticFileServing, &StaticFileServing::onRequestNeedsReply);
Debug(_log, "Instance created");
@@ -38,8 +42,17 @@ void WebServer::onServerStarted (quint16 port)
{
Info(_log, "Started on port %d name '%s'", port ,_server->getServerName().toStdString().c_str());
BonjourServiceRegister *bonjourRegister_http = new BonjourServiceRegister();
bonjourRegister_http->registerService("_hyperiond-http._tcp", port);
if(_serviceRegister == nullptr)
{
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-http._tcp", port);
}
else if( _serviceRegister->getPort() != port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-http._tcp", port);
}
}
void WebServer::onServerStopped () {
@@ -57,10 +70,8 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
{
const QJsonObject& obj = config.object();
bool webconfigEnable = obj["enable"].toBool(true);
_baseUrl = obj["document_root"].toString(WEBSERVER_DEFAULT_PATH);
if ( (_baseUrl != ":/webconfig") && !_baseUrl.trimmed().isEmpty())
{
QFileInfo info(_baseUrl);
@@ -81,10 +92,10 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
_port = obj["port"].toInt(WEBSERVER_DEFAULT_PORT);
stop();
}
if ( webconfigEnable )
{
start();
}
// eval if the port is available, will be incremented if not
NetUtils::portAvailable(_port, _log);
start();
}
}

View File

@@ -1,13 +1,18 @@
#include "WebSocketClient.h"
#include "QtHttpRequest.h"
#include "QtHttpHeader.h"
// hyperion includes
#include <hyperion/Hyperion.h>
// JsonAPI includes
#include <api/JsonAPI.h>
// qt includes
#include "QtHttpRequest.h"
#include "QtHttpHeader.h"
#include <QTcpSocket>
#include <QtEndian>
#include <QCryptographicHash>
#include <QJsonObject>
WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObject* parent)
: QObject(parent)