From 5dc59344c4553dd6e34b401b7b7afa986ee6a26b Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 8 Feb 2016 16:56:23 +0100 Subject: [PATCH 01/19] forward protobuf messages. configure (send proto messages to two other hyperiond): "protoServer" : { "port" : 19446, "forward" : [ "192.168.0.10:19445", "192.168.0.11:19445" ] }, Former-commit-id: 33af219cfce99609ca7245d662dc0f0561013bbd --- include/protoserver/ProtoConnection.h | 8 ++++---- include/protoserver/ProtoServer.h | 4 +++- libsrc/protoserver/ProtoClientConnection.cpp | 17 ++++++++++++++++- libsrc/protoserver/ProtoClientConnection.h | 8 +++++++- libsrc/protoserver/ProtoServer.cpp | 7 +++++-- src/hyperiond/hyperiond.cpp | 14 +++++++++++++- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index bb41e1b7..a61947fe 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -67,10 +67,6 @@ public: /// void clearAll(); -private: - /// Try to connect to the Hyperion host - void connectToHost(); - /// /// Send a command message and receive its reply /// @@ -78,6 +74,10 @@ private: /// void sendMessage(const proto::HyperionRequest & message); +private: + /// Try to connect to the Hyperion host + void connectToHost(); + /// /// Parse a reply message /// diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index dae57481..c18b38fb 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,6 +6,7 @@ // Qt includes #include #include +#include // Hyperion includes #include @@ -27,7 +28,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); ~ProtoServer(); /// @@ -56,4 +57,5 @@ private: /// List with open connections QSet _openConnections; + QStringList _forwardClients; }; diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 165315f7..2f0cc8d3 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,11 +30,22 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + for (int i = 0; i < forwardClientList.size(); ++i) { + std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); + p->setSkipReply(true); + _proxy_connections << p; + } + } ProtoClientConnection::~ProtoClientConnection() { delete _socket; + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -81,6 +92,10 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { + // forward messages + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(message); + switch (message.command()) { case proto::HyperionRequest::COLOR: diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index ec7d2e1c..a0c1186e 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -6,12 +6,14 @@ // Qt includes #include #include +#include // Hyperion includes #include // proto includes #include "message.pb.h" +#include "protoserver/ProtoConnection.h" class ImageProcessor; @@ -28,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); /// /// Destructor @@ -123,4 +125,8 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index a1afa30c..54d8611b 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -5,12 +5,15 @@ #include #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : QObject(), _hyperion(hyperion), _server(), _openConnections() { + for (int i = 0; i < forwardClientList->size(); ++i) + _forwardClients << forwardClientList->at(i); + if (!_server.listen(QHostAddress::Any, port)) { throw std::runtime_error("Proto server could not bind to port"); @@ -39,7 +42,7 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); _openConnections.insert(connection); // register slot for cleaning up after the connection closed diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 032d44db..d96b345a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -1,6 +1,7 @@ // C++ includes #include #include +#include // QT includes #include @@ -368,7 +369,18 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt()); + QStringList forwardClientList; + + if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) + { + for (const Json::Value& client : protoServerConfig["forward"]) + { + forwardClientList << client.asString().c_str(); + std::cout << client.asString() << std::endl; + } + } + + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From b01b5eb005d51e7cf35de62a76b908e686d4e994 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 18:25:18 +0100 Subject: [PATCH 02/19] - prepare general way to send (proto) messages. currently only incomming protomessages are forwarded - begin impl. of json server Former-commit-id: 8f9237cd57ada1e84dc05e60b9ad723e47fd57b1 --- include/hyperion/Hyperion.h | 9 ++ include/hyperion/MessageForwarder.h | 31 +++++ include/protoserver/ProtoServer.h | 15 ++- libsrc/hyperion/CMakeLists.txt | 134 ++++++++++--------- libsrc/hyperion/Hyperion.cpp | 30 +++++ libsrc/hyperion/MessageForwarder.cpp | 34 +++++ libsrc/jsonserver/JsonClientConnection.cpp | 67 +++++++++- libsrc/jsonserver/JsonClientConnection.h | 6 + libsrc/protoserver/ProtoClientConnection.cpp | 16 +-- libsrc/protoserver/ProtoClientConnection.h | 7 +- libsrc/protoserver/ProtoServer.cpp | 29 +++- src/hyperiond/hyperiond.cpp | 13 +- 12 files changed, 287 insertions(+), 104 deletions(-) create mode 100644 include/hyperion/MessageForwarder.h create mode 100644 libsrc/hyperion/MessageForwarder.cpp diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index b6ed0946..811f0199 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -13,6 +13,7 @@ // Hyperion includes #include #include +#include // Effect engine includes #include @@ -125,6 +126,10 @@ public slots: /// Tell Hyperion that the transforms have changed and the leds need to be updated void transformsUpdated(); + /// Returns MessageForwarder Object + /// @return instance of message forwarder object + MessageForwarder * getForwarder(); + /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next /// lower priority channel (or off if no more channels are set) @@ -168,6 +173,7 @@ public: static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); + static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig); signals: /// Signal which is emitted when a priority channel is actively cleared @@ -201,6 +207,9 @@ private: /// Effect engine EffectEngine * _effectEngine; + // proto and json Message forwarder + MessageForwarder * _messageForwarder; + /// The timer for handling priority channel timeouts QTimer _timer; }; diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h new file mode 100644 index 00000000..467d0d35 --- /dev/null +++ b/include/hyperion/MessageForwarder.h @@ -0,0 +1,31 @@ +#pragma once + +// STL includes +#include +#include +#include +#include + +// QT includes +#include +#include + +// Utils includes +#include +class MessageForwarder +{ +public: + MessageForwarder(); + ~MessageForwarder(); + + void addJsonSlave(std::string slave); + void addProtoSlave(std::string slave); + void sendMessage(); + + QStringList getProtoSlaves(); + +private: + bool _running; + + QStringList _protoSlaves; +}; diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index c18b38fb..1d530caa 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,12 +6,19 @@ // Qt includes #include #include +#include #include // Hyperion includes #include +// forward decl class ProtoClientConnection; +class ProtoConnection; + +namespace proto { +class HyperionRequest; +} /// /// This class creates a TCP server which accepts connections wich can then send @@ -28,7 +35,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445); ~ProtoServer(); /// @@ -48,6 +55,8 @@ private slots: /// void closedConnection(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); + private: /// Hyperion instance Hyperion * _hyperion; @@ -58,4 +67,8 @@ private: /// List with open connections QSet _openConnections; QStringList _forwardClients; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 1434f105..3a277a7e 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -1,66 +1,68 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) - -# Group the headers that go through the MOC compiler -SET(Hyperion_QT_HEADERS - ${CURRENT_HEADER_DIR}/Hyperion.h - - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h -) - -SET(Hyperion_HEADERS - ${CURRENT_HEADER_DIR}/ImageProcessor.h - ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h - ${CURRENT_HEADER_DIR}/ImageToLedsMap.h - ${CURRENT_HEADER_DIR}/LedString.h - ${CURRENT_HEADER_DIR}/PriorityMuxer.h - - ${CURRENT_SOURCE_DIR}/MultiColorTransform.h -) - -SET(Hyperion_SOURCES - ${CURRENT_SOURCE_DIR}/Hyperion.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp - ${CURRENT_SOURCE_DIR}/LedString.cpp - ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp - - ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp - ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp -) - -set(Hyperion_RESOURCES - ${CURRENT_SOURCE_DIR}/resource.qrc -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -endif(ENABLE_QT5) - -add_library(hyperion - ${Hyperion_HEADERS} - ${Hyperion_QT_HEADERS} - ${Hyperion_HEADERS_MOC} - ${Hyperion_SOURCES} - ${Hyperion_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(hyperion Widgets) -endif(ENABLE_QT5) - -target_link_libraries(hyperion - blackborder - hyperion-utils - leddevice - effectengine - serialport - ${QT_LIBRARIES} -) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) + +# Group the headers that go through the MOC compiler +SET(Hyperion_QT_HEADERS + ${CURRENT_HEADER_DIR}/Hyperion.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h + + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h +) + +SET(Hyperion_HEADERS + ${CURRENT_HEADER_DIR}/ImageProcessor.h + ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h + ${CURRENT_HEADER_DIR}/ImageToLedsMap.h + ${CURRENT_HEADER_DIR}/LedString.h + ${CURRENT_HEADER_DIR}/PriorityMuxer.h + + ${CURRENT_SOURCE_DIR}/MultiColorTransform.h +) + +SET(Hyperion_SOURCES + ${CURRENT_SOURCE_DIR}/Hyperion.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp + ${CURRENT_SOURCE_DIR}/LedString.cpp + ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp + + ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp + ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp +) + +set(Hyperion_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) +QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) + +add_library(hyperion + ${Hyperion_HEADERS} + ${Hyperion_QT_HEADERS} + ${Hyperion_HEADERS_MOC} + ${Hyperion_SOURCES} + ${Hyperion_RESOURCES_RCC} +) + +if(ENABLE_QT5) +qt5_use_modules(hyperion Widgets) +endif(ENABLE_QT5) + +target_link_libraries(hyperion + blackborder + hyperion-utils + leddevice + effectengine + serialport + ${QT_LIBRARIES} +) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 37c77927..ed23fb30 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -267,12 +267,39 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, } +MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarderConfig) +{ + MessageForwarder * forwarder = new MessageForwarder(); + if ( ! forwarderConfig.isNull() ) + { + if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["json"]) + forwarder->addJsonSlave(addr.asString()); + } + + if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["proto"]) + forwarder->addProtoSlave(addr.asString()); + } + } + + return forwarder; +} + +MessageForwarder * Hyperion::getForwarder() +{ + return _messageForwarder; +} + Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _device(LedDeviceFactory::construct(jsonConfig["device"])), _effectEngine(nullptr), + _messageForwarder(createMessageForwarder(jsonConfig["forwarder"])), _timer() { if (!_raw2ledTransform->verifyTransforms()) @@ -314,6 +341,9 @@ Hyperion::~Hyperion() // delete the color transform delete _raw2ledTransform; + + // delete the message forwarder + delete _messageForwarder; } unsigned Hyperion::getLedCount() const diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp new file mode 100644 index 00000000..8da277e2 --- /dev/null +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -0,0 +1,34 @@ +#include + + +MessageForwarder::MessageForwarder() : +_running(false) +{ +} + +MessageForwarder::~MessageForwarder() +{ +} + + +void MessageForwarder::addJsonSlave(std::string slave) +{ + std::cout << slave << std::endl; +} + +void MessageForwarder::addProtoSlave(std::string slave) +{ + _protoSlaves << QString(slave.c_str()); +} + +void MessageForwarder::sendMessage() +{ + if ( ! _running ) + return; + +} + +QStringList MessageForwarder::getProtoSlaves() +{ + return _protoSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 87fb7c1f..1b700b25 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -250,8 +250,22 @@ void JsonClientConnection::handleMessage(const std::string &messageString) handleNotImplemented(); } + +void JsonClientConnection::forwardJsonMessage(const Json::Value & message) +{ + QTcpSocket client; + client.connectToHost(QHostAddress("127.0.0.1"), 19444); + if ( client.waitForConnected(500) ) + { + sendMessage(message,&client); + client.close(); + } +} + void JsonClientConnection::handleColorCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -289,6 +303,8 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message) void JsonClientConnection::handleImageCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -320,6 +336,8 @@ void JsonClientConnection::handleImageCommand(const Json::Value &message) void JsonClientConnection::handleEffectCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -418,6 +436,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) void JsonClientConnection::handleClearCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); @@ -428,8 +448,10 @@ void JsonClientConnection::handleClearCommand(const Json::Value &message) sendSuccessReply(); } -void JsonClientConnection::handleClearallCommand(const Json::Value &) +void JsonClientConnection::handleClearallCommand(const Json::Value & message) { + forwardJsonMessage(message); + // clear priority _hyperion->clearall(); @@ -530,10 +552,51 @@ void JsonClientConnection::sendMessage(const Json::Value &message) response.append(serializedReply.c_str(), serializedReply.length()); - _socket->write(response.data(), response.length()); + _socket->write(response.data(), response.length()); } } + +void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * socket) +{ + // serialize message (FastWriter already appends a newline) + std::string serializedMessage = Json::FastWriter().write(message); + + // write message + socket->write(serializedMessage.c_str()); + if (!socket->waitForBytesWritten()) + { + //std::cout << "Error while writing data to host" << std::endl; + return; + } + + // read reply data + QByteArray serializedReply; + while (!serializedReply.contains('\n')) + { + // receive reply + if (!socket->waitForReadyRead()) + { + //std::cout << "Error while reading data from host" << std::endl; + return; + } + + serializedReply += socket->readAll(); + } + int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message + + // parse reply data + Json::Reader jsonReader; + Json::Value reply; + if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply)) + { + //std::cout << "Error while parsing reply: invalid json" << std::endl; + return; + } + +} + + void JsonClientConnection::sendSuccessReply() { // create reply diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h index 6575388a..01db54b1 100644 --- a/libsrc/jsonserver/JsonClientConnection.h +++ b/libsrc/jsonserver/JsonClientConnection.h @@ -124,6 +124,7 @@ private: /// @param message The JSON message to send /// void sendMessage(const Json::Value & message); + void sendMessage(const Json::Value & message, QTcpSocket * socket); /// /// Send a standard reply indicating success @@ -147,6 +148,11 @@ private: /// void handleWebSocketFrame(); + /// + /// forward json message + /// + void forwardJsonMessage(const Json::Value & message); + private: /// /// Check if a JSON messag is valid according to a given JSON schema diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 2f0cc8d3..d1f087cd 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,22 +30,11 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); - - for (int i = 0; i < forwardClientList.size(); ++i) { - std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; - ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); - p->setSkipReply(true); - _proxy_connections << p; - } - } ProtoClientConnection::~ProtoClientConnection() { delete _socket; - - while (!_proxy_connections.isEmpty()) - delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -93,8 +82,7 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { // forward messages - for (int i = 0; i < _proxy_connections.size(); ++i) - _proxy_connections.at(i)->sendMessage(message); + emit newMessage(&message); switch (message.command()) { diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index a0c1186e..c68f56e0 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -30,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); /// /// Destructor @@ -43,6 +43,7 @@ signals: /// @param connection This connection object /// void connectionClosed(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); private slots: /// @@ -125,8 +126,4 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; - - /// Hyperion proto connection object for forwarding - QList _proxy_connections; - }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index 54d8611b..a7c51ca8 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -2,17 +2,27 @@ #include // project includes +#include #include +#include "protoserver/ProtoConnection.h" #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : QObject(), _hyperion(hyperion), _server(), _openConnections() { - for (int i = 0; i < forwardClientList->size(); ++i) - _forwardClients << forwardClientList->at(i); + + MessageForwarder * forwarder = hyperion->getForwarder(); + QStringList slaves = forwarder->getProtoSlaves(); + + for (int i = 0; i < slaves.size(); ++i) { + std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); + p->setSkipReply(true); + _proxy_connections << p; + } if (!_server.listen(QHostAddress::Any, port)) { @@ -28,6 +38,9 @@ ProtoServer::~ProtoServer() foreach (ProtoClientConnection * connection, _openConnections) { delete connection; } + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } uint16_t ProtoServer::getPort() const @@ -42,14 +55,22 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); _openConnections.insert(connection); // 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*))); + } } +void ProtoServer::newMessage(const proto::HyperionRequest * message) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(*message); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index d96b345a..7bb5e60e 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -369,18 +369,7 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - QStringList forwardClientList; - - if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) - { - for (const Json::Value& client : protoServerConfig["forward"]) - { - forwardClientList << client.asString().c_str(); - std::cout << client.asString() << std::endl; - } - } - - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From df91527557342e7925c57de81610b67485d3d9ce Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 20:53:03 +0100 Subject: [PATCH 03/19] implement json forwarder Former-commit-id: 5519118304bd5690e6b512481347579339e78ac9 --- include/hyperion/MessageForwarder.h | 13 ++++++++--- libsrc/hyperion/Hyperion.cpp | 6 ++++++ libsrc/hyperion/MessageForwarder.cpp | 25 ++++++++++++++++------ libsrc/jsonserver/JsonClientConnection.cpp | 14 ++++++++---- libsrc/protoserver/ProtoServer.cpp | 1 - 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 467d0d35..0a3c1b19 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -9,12 +9,19 @@ // QT includes #include #include +#include // Utils includes #include class MessageForwarder { public: + + struct JsonSlaveAddress { + QHostAddress addr; + quint16 port = 19444; + }; + MessageForwarder(); ~MessageForwarder(); @@ -23,9 +30,9 @@ public: void sendMessage(); QStringList getProtoSlaves(); + QList getJsonSlaves(); private: - bool _running; - - QStringList _protoSlaves; + QStringList _protoSlaves; + QList _jsonSlaves; }; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index ed23fb30..2463ed15 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -275,13 +275,19 @@ MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarde if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) { for (const Json::Value& addr : forwarderConfig["json"]) + { + std::cout << "Json forward to " << addr.asString() << std::endl; forwarder->addJsonSlave(addr.asString()); + } } if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) { for (const Json::Value& addr : forwarderConfig["proto"]) + { + std::cout << "Proto forward to " << addr.asString() << std::endl; forwarder->addProtoSlave(addr.asString()); + } } } diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 8da277e2..be9c9825 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,8 +1,7 @@ #include -MessageForwarder::MessageForwarder() : -_running(false) +MessageForwarder::MessageForwarder() { } @@ -13,7 +12,19 @@ MessageForwarder::~MessageForwarder() void MessageForwarder::addJsonSlave(std::string slave) { - std::cout << slave << std::endl; + QStringList parts = QString(slave.c_str()).split(":"); + if (parts.size() != 2) + throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(slave.c_str()).toStdString()); + + bool ok; + quint16 port = parts[1].toUShort(&ok); + if (!ok) + throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); + + JsonSlaveAddress c; + c.addr = QHostAddress(parts[0]); + c.port = port; + _jsonSlaves << c; } void MessageForwarder::addProtoSlave(std::string slave) @@ -23,12 +34,14 @@ void MessageForwarder::addProtoSlave(std::string slave) void MessageForwarder::sendMessage() { - if ( ! _running ) - return; - } QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; } + +QList MessageForwarder::getJsonSlaves() +{ + return _jsonSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 1b700b25..e4dbc096 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -16,6 +16,7 @@ // hyperion util includes #include #include +#include #include #include @@ -254,11 +255,16 @@ void JsonClientConnection::handleMessage(const std::string &messageString) void JsonClientConnection::forwardJsonMessage(const Json::Value & message) { QTcpSocket client; - client.connectToHost(QHostAddress("127.0.0.1"), 19444); - if ( client.waitForConnected(500) ) + QList list = _hyperion->getForwarder()->getJsonSlaves(); + + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { - std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 2b1ac785d16da8c4dba39c5adc2585e95bf2fe66 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 21:21:56 +0100 Subject: [PATCH 04/19] add example configs Former-commit-id: 8176d915580bd0bd3d1604bcbf678f988e1d85d8 --- config/hyperion.config.json | 14 ++++++++++++++ config/hyperion_x86.config.json | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 0f8404a9..291086db 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -23,6 +23,20 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 4121c499..ec21a35b 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -19,6 +19,21 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: From 7f5b141f435efb4747ca57412dd2732a1cb09741 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:16:59 +0100 Subject: [PATCH 05/19] forwarder: remove default init of port, could procude compile errors and it is not needed Former-commit-id: 08d7524a2cda53136ae8c72d5fdc1f95f51a23e7 --- include/hyperion/MessageForwarder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 0a3c1b19..9cc034fc 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -19,7 +19,7 @@ public: struct JsonSlaveAddress { QHostAddress addr; - quint16 port = 19444; + quint16 port; }; MessageForwarder(); From 738bafee994a266365d25b090ac3ede8c820d84e Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:59:31 +0100 Subject: [PATCH 06/19] forwarder: add missing include Former-commit-id: 58d07b73ff1ad321a9cfbf73895b438665ce3c14 --- libsrc/hyperion/MessageForwarder.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index be9c9825..1ae4bef6 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,3 +1,6 @@ +// STL includes +#include + #include From 629461b944a94c55c02736b9a8ab28f23ff51e1a Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:41:40 +0100 Subject: [PATCH 07/19] implement proto forwarding for hyperiond internal v4l2 grabber cleanup Former-commit-id: 669f139386633e3435cdc33639134819464afd4d --- include/grabber/V4L2Wrapper.h | 1 + include/hyperion/MessageForwarder.h | 1 - include/protoserver/ProtoServer.h | 7 +++ libsrc/grabber/v4l2/V4L2Wrapper.cpp | 3 ++ libsrc/hyperion/CMakeLists.txt | 2 +- libsrc/hyperion/MessageForwarder.cpp | 4 -- libsrc/protoserver/ProtoServer.cpp | 6 +++ src/hyperiond/hyperiond.cpp | 78 ++++++++++++++++------------ 8 files changed, 62 insertions(+), 40 deletions(-) diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h index 2a9ece2c..2b8dc74a 100644 --- a/include/grabber/V4L2Wrapper.h +++ b/include/grabber/V4L2Wrapper.h @@ -44,6 +44,7 @@ public slots: signals: void emitColors(int priority, const std::vector &ledColors, const int timeout_ms); + void emitImage(int priority, const Image & image, const int timeout_ms); private slots: void newFrame(const Image & image); diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 9cc034fc..c9c27fe5 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,6 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - void sendMessage(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index 1d530caa..520848a9 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -12,6 +12,10 @@ // Hyperion includes #include +// hyperion includes +#include +#include + // forward decl class ProtoClientConnection; class ProtoConnection; @@ -43,6 +47,9 @@ public: /// uint16_t getPort() const; +public slots: + void sendImageToProtoSlaves(int priority, const Image & image, int duration_ms); + private slots: /// /// Slot which is called when a client tries to create a new connection diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index 76b16ab7..cbccf41b 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -94,6 +94,9 @@ void V4L2Wrapper::newFrame(const Image &image) // process the new image _processor->process(image, _ledColors); + // forward to other hyperions + emit emitImage(_priority, image, _timeout_ms); + // send colors to Hyperion emit emitColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 3a277a7e..ebd25254 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -6,7 +6,6 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) # Group the headers that go through the MOC compiler SET(Hyperion_QT_HEADERS ${CURRENT_HEADER_DIR}/Hyperion.h - ${CURRENT_HEADER_DIR}/MessageForwarder.h ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h ) @@ -19,6 +18,7 @@ SET(Hyperion_HEADERS ${CURRENT_HEADER_DIR}/PriorityMuxer.h ${CURRENT_SOURCE_DIR}/MultiColorTransform.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h ) SET(Hyperion_SOURCES diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 1ae4bef6..09bcf685 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -35,10 +35,6 @@ void MessageForwarder::addProtoSlave(std::string slave) _protoSlaves << QString(slave.c_str()); } -void MessageForwarder::sendMessage() -{ -} - QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index ca1b6358..03c334d4 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -70,6 +70,12 @@ void ProtoServer::newMessage(const proto::HyperionRequest * message) _proxy_connections.at(i)->sendMessage(*message); } +void ProtoServer::sendImageToProtoSlaves(int priority, const Image & image, int duration_ms) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->setImage(image, priority, duration_ms); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 7bb5e60e..fe24762a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -189,6 +189,39 @@ int main(int argc, char** argv) std::cout << "XBMC video checker created and started" << std::endl; } +// ---- network services ----- + + // Create Json server if configuration is present + JsonServer * jsonServer = nullptr; + if (config.isMember("jsonServer")) + { + const Json::Value & jsonServerConfig = config["jsonServer"]; + jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); + std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; + } + +#ifdef ENABLE_PROTOBUF + // Create Proto server if configuration is present + ProtoServer * protoServer = nullptr; + if (config.isMember("protoServer")) + { + const Json::Value & protoServerConfig = config["protoServer"]; + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); + std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; + } +#endif + + // Create Boblight server if configuration is present + BoblightServer * boblightServer = nullptr; + if (config.isMember("boblightServer")) + { + const Json::Value & boblightServerConfig = config["boblightServer"]; + boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); + std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; + } + +// ---- grabber ----- + #ifdef ENABLE_DISPMANX // Construct and start the frame-grabber if the configuration is present DispmanxWrapper * dispmanx = nullptr; @@ -214,7 +247,7 @@ int main(int argc, char** argv) #if !defined(ENABLE_OSX) && !defined(ENABLE_FB) if (config.isMember("framegrabber")) { - std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -246,14 +279,19 @@ int main(int argc, char** argv) grabberConfig.get("cropTop", 0).asInt(), grabberConfig.get("cropBottom", 0).asInt()); + #ifdef ENABLE_PROTOBUF + QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + v4l2Grabber->start(); std::cout << "V4l2 grabber created and started" << std::endl; } #else if (config.isMember("grabber-v4l2")) { - std::cerr << "The v4l2 grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl; } + #endif #ifdef ENABLE_AMLOGIC @@ -309,12 +347,12 @@ int main(int argc, char** argv) #else if (config.isMember("framebuffergrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) else if (config.isMember("framegrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -344,44 +382,16 @@ int main(int argc, char** argv) #else if (config.isMember("osxgrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB) else if (config.isMember("framegrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif - // Create Json server if configuration is present - JsonServer * jsonServer = nullptr; - if (config.isMember("jsonServer")) - { - const Json::Value & jsonServerConfig = config["jsonServer"]; - jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); - std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; - } - -#ifdef ENABLE_PROTOBUF - // Create Proto server if configuration is present - ProtoServer * protoServer = nullptr; - if (config.isMember("protoServer")) - { - const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); - std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; - } -#endif - - // Create Boblight server if configuration is present - BoblightServer * boblightServer = nullptr; - if (config.isMember("boblightServer")) - { - const Json::Value & boblightServerConfig = config["boblightServer"]; - boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); - std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; - } // run the application int rc = app.exec(); From 46c5a2ec051b68ea7d1c774062e04bb5d71c8b63 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:56:20 +0100 Subject: [PATCH 08/19] use correct include for std::runtime_error Former-commit-id: a96b727cc0258fda9684f5df52084dd8d96068e3 --- libsrc/hyperion/MessageForwarder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 09bcf685..2e277fc8 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,5 +1,5 @@ // STL includes -#include +#include #include From a9e8f0264a0b6a1262b99e59dfb0b6d4cd854488 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 17 Feb 2016 00:44:06 +0100 Subject: [PATCH 09/19] implement proto forwarding for osxgrabber and framebuffer. prepare forwarding in amlogic and dispmanx Former-commit-id: d67fc2b7fe8877e6eadf31a8c76e4a68110c6680 --- include/grabber/DispmanxWrapper.h | 3 +++ include/grabber/FramebufferWrapper.h | 3 +++ include/grabber/OsxWrapper.h | 3 +++ libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 4 +++- libsrc/grabber/framebuffer/FramebufferWrapper.cpp | 3 ++- libsrc/grabber/osx/OsxWrapper.cpp | 3 ++- libsrc/leddevice/LedDeviceFadeCandy.cpp | 2 +- src/hyperiond/hyperiond.cpp | 12 ++++++++++++ 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 4868c1a0..2df81340 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/FramebufferWrapper.h b/include/grabber/FramebufferWrapper.h index f633ae55..75252d24 100644 --- a/include/grabber/FramebufferWrapper.h +++ b/include/grabber/FramebufferWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/OsxWrapper.h b/include/grabber/OsxWrapper.h index 39ac1a7e..fa597c67 100644 --- a/include/grabber/OsxWrapper.h +++ b/include/grabber/OsxWrapper.h @@ -69,6 +69,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index c9d2b22c..84657fc8 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -51,10 +51,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + //emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } + void DispmanxWrapper::stop() { // Stop the timer, effectivly stopping the process diff --git a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp index abc6400c..96506d55 100644 --- a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp +++ b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp @@ -46,8 +46,9 @@ void FramebufferWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void FramebufferWrapper::stop() diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index 6d6f9a00..da8b039e 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -46,8 +46,9 @@ void OsxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void OsxWrapper::stop() diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index 685795a9..2e6a1411 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,6 +1,6 @@ #include "LedDeviceFadeCandy.h" -static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds +static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds static const unsigned OPC_SET_PIXELS = 0; // OPC command codes static const unsigned OPC_HEADER_SIZE = 4; // OPC header size diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index fe24762a..b300aefc 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -240,6 +240,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + dispmanx->start(); std::cout << "Frame grabber created and started" << std::endl; } @@ -341,6 +345,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + fbGrabber->start(); std::cout << "Framebuffer grabber created and started" << std::endl; } @@ -375,6 +383,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode))); QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode))); } + + #ifdef ENABLE_PROTOBUF + QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif osxGrabber->start(); std::cout << "OSX grabber created and started" << std::endl; From 0f17e031e85dc7359ce1a0cbb842b07d2b2aa82a Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 10:32:38 +0100 Subject: [PATCH 10/19] basic loop connection detection. prevent if you configure forward to 127.0.0.1: and your server has the same port. But this doesn't protect if not forwarded to localhost "127.0.0.1". Loop connections across different hosts arn't detected too. Former-commit-id: 464a80708ebd11c0f7c83dc87a1afe0f10e0e078 --- libsrc/jsonserver/JsonServer.cpp | 8 ++++++++ libsrc/protoserver/ProtoServer.cpp | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/libsrc/jsonserver/JsonServer.cpp b/libsrc/jsonserver/JsonServer.cpp index 4efe855c..4cd7f411 100644 --- a/libsrc/jsonserver/JsonServer.cpp +++ b/libsrc/jsonserver/JsonServer.cpp @@ -16,6 +16,14 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) : throw std::runtime_error("Json server could not bind to port"); } + QList list = _hyperion->getForwarder()->getJsonSlaves(); + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { + if ( QString("127.0.0.1:%1").arg(port) == slaves.at(i) ) { + throw std::runtime_error("Loop between proto server and forwarder detected. Fix your config!"); + } + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 736d841567f3e482f2d8f9d2e00c6908be8b05e8 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 23:32:42 +0100 Subject: [PATCH 11/19] update rpi bins Former-commit-id: 851c37754b2e9a020d9a82c90438db96988f472d --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 44bbdc58..94286a16 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -5c164e4ff52076a530461cdf6966943d52cd39df \ No newline at end of file +d6c2a97271d37ffb04fa2e1e9ce7812d5b132811 \ No newline at end of file From ec67caf24ed3d7d9f457190f294a92e12865a024 Mon Sep 17 00:00:00 2001 From: redpanther Date: Fri, 19 Feb 2016 13:31:08 +0100 Subject: [PATCH 12/19] add ability to convert an image to RGB color order forwarder: add flag to detect if forwarding is enabled Former-commit-id: c814651ec4973fe3b2bfca7c0370a0bac752f025 --- include/hyperion/MessageForwarder.h | 3 ++- include/utils/Image.h | 21 ++++++++++++++++++ libsrc/hyperion/MessageForwarder.cpp | 5 +++++ test/TestRgbImage.cpp | 32 ++++++++++++++++++++++------ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index c9c27fe5..a762ae41 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,8 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - + + bool protoForwardingEnabled(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/utils/Image.h b/include/utils/Image.h index 0a8ca31a..ece6155a 100644 --- a/include/utils/Image.h +++ b/include/utils/Image.h @@ -5,6 +5,8 @@ #include #include #include +#include + template class Image @@ -183,6 +185,25 @@ public: { return _pixels; } + + + /// + /// Convert image of any color order to a RGB image. + /// + /// @param[out] image The image that buffers the output + /// + void toRgb(Image& image) + { + image.resize(_width, _height); + const unsigned imageSize = _width * _height; + + for (unsigned idx=0; idx MessageForwarder::getJsonSlaves() { return _jsonSlaves; } + +bool MessageForwarder::protoForwardingEnabled() +{ + return ! _protoSlaves.empty(); +} diff --git a/test/TestRgbImage.cpp b/test/TestRgbImage.cpp index 374408f5..67773763 100644 --- a/test/TestRgbImage.cpp +++ b/test/TestRgbImage.cpp @@ -4,22 +4,42 @@ // Utils includes #include +#include #include +#include +#include int main() { std::cout << "Constructing image" << std::endl; - Image image(64, 64, ColorRgb::BLACK); + int width = 64; + int height = 64; + Image image_rgb(width, height, ColorRgb::BLACK); + Image image_bgr(image_rgb.width(), image_rgb.height(), ColorBgr::BLACK); std::cout << "Writing image" << std::endl; - for (unsigned y=0; y<64; ++y) + unsigned l = width * height; + + // BGR + for (unsigned i=0; i Date: Wed, 24 Feb 2016 14:34:19 +0100 Subject: [PATCH 13/19] implement dispmanx forwarding a a separate dispmanx wrapper implement forwarding for amlogic grabber Former-commit-id: 8a793d24bd083f9eca07c34ec3b222f0e54b4426 --- include/grabber/AmlogicWrapper.h | 6 ++ .../grabber}/DispmanxFrameGrabber.h | 0 include/grabber/DispmanxWrapper.h | 3 + libsrc/grabber/amlogic/AmlogicWrapper.cpp | 9 +- libsrc/grabber/dispmanx/CMakeLists.txt | 81 ++++++++-------- .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 2 +- libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 10 +- src/CMakeLists.txt | 5 + src/hyperion-dispmanx/CMakeLists.txt | 70 ++++++++++++++ src/hyperion-dispmanx/DispmanxWrapper.cpp | 38 ++++++++ src/hyperion-dispmanx/DispmanxWrapper.h | 42 +++++++++ src/hyperion-dispmanx/hyperion-dispmanx.cpp | 92 +++++++++++++++++++ 12 files changed, 314 insertions(+), 44 deletions(-) rename {libsrc/grabber/dispmanx => include/grabber}/DispmanxFrameGrabber.h (100%) create mode 100644 src/hyperion-dispmanx/CMakeLists.txt create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.cpp create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.h create mode 100644 src/hyperion-dispmanx/hyperion-dispmanx.cpp diff --git a/include/grabber/AmlogicWrapper.h b/include/grabber/AmlogicWrapper.h index 0ce70b80..c712b60e 100644 --- a/include/grabber/AmlogicWrapper.h +++ b/include/grabber/AmlogicWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; @@ -91,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h similarity index 100% rename from libsrc/grabber/dispmanx/DispmanxFrameGrabber.h rename to include/grabber/DispmanxFrameGrabber.h diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 2df81340..e64adf47 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -94,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index 1dca6764..b77f1612 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -26,6 +26,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig // Configure the timer to generate events every n milliseconds _timer.setInterval(_updateInterval_ms); _timer.setSingleShot(false); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); _processor->setSize(grabWidth, grabHeight); @@ -55,8 +56,14 @@ void AmlogicWrapper::action() return; } - _processor->process(_image, _ledColors); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index d4d64b72..27c1f11c 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,40 +1,41 @@ - -# Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) - -# Group the headers that go through the MOC compiler -SET(DispmanxGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/DispmanxWrapper.h -) - -SET(DispmanxGrabberHEADERS - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h -) - -SET(DispmanxGrabberSOURCES - ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -else(ENABLE_QT5) -QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -endif(ENABLE_QT5) - -add_library(dispmanx-grabber - ${DispmanxGrabberHEADERS} - ${DispmanxGrabberQT_HEADERS} - ${DispmanxGrabberHEADERS_MOC} - ${DispmanxGrabberSOURCES} -) - -target_link_libraries(dispmanx-grabber - hyperion - ${QT_LIBRARIES} - ${BCM_LIBRARIES}) + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) +include_directories(${BCM_INCLUDE_DIRS}) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) + +# Group the headers that go through the MOC compiler +SET(DispmanxGrabberQT_HEADERS + ${CURRENT_HEADER_DIR}/DispmanxWrapper.h +) + +SET(DispmanxGrabberHEADERS + ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h +) + +SET(DispmanxGrabberSOURCES + ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp + ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +endif(ENABLE_QT5) + +add_library(dispmanx-grabber + ${DispmanxGrabberHEADERS} + ${DispmanxGrabberQT_HEADERS} + ${DispmanxGrabberHEADERS_MOC} + ${DispmanxGrabberSOURCES} +) + +target_link_libraries(dispmanx-grabber + hyperion + ${QT_LIBRARIES} + ${BCM_LIBRARIES} +) diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index 1f6516a4..53397acf 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -4,7 +4,7 @@ #include // Local includes -#include "DispmanxFrameGrabber.h" +#include "grabber/DispmanxFrameGrabber.h" DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) : _vc_display(0), diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index 84657fc8..7868ce34 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -9,7 +9,7 @@ // Dispmanx grabber includes #include -#include "DispmanxFrameGrabber.h" +#include DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : @@ -28,6 +28,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe _timer.setSingleShot(false); _processor->setSize(grabWidth, grabHeight); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); // Connect the QTimer to this QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); @@ -51,7 +52,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - //emit emitImage(_priority, _image, _timeout_ms); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a291850..f55af750 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,4 +15,9 @@ if(ENABLE_PROTOBUF) if(ENABLE_X11) add_subdirectory(hyperion-x11) endif() + + if(ENABLE_DISPMANX) + add_subdirectory(hyperion-dispmanx) + endif() + endif() diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt new file mode 100644 index 00000000..4d48174e --- /dev/null +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -0,0 +1,70 @@ +# Configure minimum CMAKE version +cmake_minimum_required(VERSION 2.8) + +# Set the project name +project(hyperion-dispmanx) + +if(ENABLE_QT5) + find_package(Qt5Widgets REQUIRED) +else(ENABLE_QT5) + # find Qt4 + find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) +endif(ENABLE_QT5) + +# Find the BCM-package (VC control) +#find_package(BCM REQUIRED) +SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) +SET( BCM_LIBRARIES "" ) +ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) + + + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver + ${QT_INCLUDES} + ${BCM_INCLUDE_DIRS} + ${PROTOBUF_INCLUDE_DIRS} +) + +set(Hyperion_Dispmanx_QT_HEADERS + DispmanxWrapper.h) + +set(Hyperion_Dispmanx_HEADERS +) + +set(Hyperion_Dispmanx_SOURCES + hyperion-dispmanx.cpp + DispmanxWrapper.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +endif(ENABLE_QT5) + +add_executable( ${PROJECT_NAME} + ${Hyperion_Dispmanx_HEADERS} + ${Hyperion_Dispmanx_SOURCES} + ${Hyperion_Dispmanx_HEADERS_MOC} +) + +target_link_libraries( ${PROJECT_NAME} + getoptPlusPlus + blackborder + hyperion-utils + protoserver + dispmanx-grabber + ${Dispmanx_LIBRARIES} + pthread +) + +if(ENABLE_QT5) + qt5_use_modules(hyperion-dispmanx Widgets Core Gui Network) +else(ENABLE_QT5) + qt4_use_modules(hyperion-dispmanx + Core + Gui + Network + ) +endif(ENABLE_QT5) diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp new file mode 100644 index 00000000..b11830a7 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-X11 includes +#include "DispmanxWrapper.h" + +DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & DispmanxWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void DispmanxWrapper::start() +{ + _timer.start(); +} + +void DispmanxWrapper::stop() +{ + _timer.stop(); +} + +void DispmanxWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h new file mode 100644 index 00000000..827a4d53 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -0,0 +1,42 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class DispmanxWrapper : public QObject +{ + Q_OBJECT +public: + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp new file mode 100644 index 00000000..c7d5fe0e --- /dev/null +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -0,0 +1,92 @@ + +// QT includes +#include +#include + +// getoptPlusPLus includes +#include + +#include "protoserver/ProtoConnectionWrapper.h" +#include "DispmanxWrapper.h" + +using namespace vlofgren; + +// save the image as screenshot +void saveScreenshot(const char * filename, const Image & image) +{ + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save(filename); +} + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("Dispmanx capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); + + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "The width of the grabbed frames [pixels]"); + IntParameter & argHeight = parameters.add (0x0, "height", "The height of the grabbed frames"); + + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + + // set defaults + argFps.setDefault(10); + argWidth.setDefault(64); + argHeight.setDefault(64); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); + + // parse all options + optionParser.parse(argc, const_cast(argv)); + + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } + + // Create the dispmanx grabbing stuff + int grabInterval = 1000 / argFps.getValue(); + DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + + if (argScreenshot.isSet()) + { + // Capture a single screenshot and finish + const Image & screenshot = dispmanxWrapper.getScreenshot(); + saveScreenshot("screenshot.png", screenshot); + } + else + { + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + + // Connect the screen capturing to the proto processing + QObject::connect(&dispmanxWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + dispmanxWrapper.start(); + + // Start the application + app.exec(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} From 8fdf97e6934138b91e7e2950f1f2fb2c53a13842 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 14:42:25 +0100 Subject: [PATCH 14/19] prepare standalone amlogic grabber activate internal amlogic grabber forwarding Former-commit-id: 21dabf759935836eef556baeb8a27e362e95ae96 --- {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h | 0 libsrc/grabber/amlogic/AmlogicGrabber.cpp | 2 +- libsrc/grabber/amlogic/AmlogicWrapper.cpp | 2 +- libsrc/grabber/amlogic/CMakeLists.txt | 2 +- src/hyperion-aml/hyperion-aml.cpp | 2 +- src/hyperiond/hyperiond.cpp | 4 ++++ 6 files changed, 8 insertions(+), 4 deletions(-) rename {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h (100%) diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.h b/include/grabber/AmlogicGrabber.h similarity index 100% rename from libsrc/grabber/amlogic/AmlogicGrabber.h rename to include/grabber/AmlogicGrabber.h diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 8eaa9799..25153142 100644 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -13,7 +13,7 @@ #include // Local includes -#include "AmlogicGrabber.h" +#include // Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic #define AMVIDEOCAP_IOC_MAGIC 'V' diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index b77f1612..29022afe 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -9,7 +9,7 @@ // Amlogic grabber includes #include -#include "AmlogicGrabber.h" +#include AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index be6cb97d..9ec98bfe 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -7,7 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) SET(AmlogicHEADERS - ${CURRENT_SOURCE_DIR}/AmlogicGrabber.h + ${CURRENT_HEADER_DIR}/AmlogicGrabber.h ) SET(AmlogicSOURCES diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 13da6686..71bcd495 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,7 +7,7 @@ // getoptPlusPLus includes #include -#include "../../libsrc/grabber/amlogic/AmlogicGrabber.h" +#include using namespace vlofgren; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index b300aefc..8af26879 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -316,6 +316,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + amlGrabber->start(); std::cout << "AMLOGIC grabber created and started" << std::endl; } From 1b6b90df51b5c13ebefc1fe9315ba1596156c63c Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 15:09:07 +0100 Subject: [PATCH 15/19] bring back hyperion.tar.gz Former-commit-id: 2e507be1aca9e58076cafc38ca10e09a65cd3998 --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 1 + 1 file changed, 1 insertion(+) create mode 100644 deploy/hyperion_rpi.tar.gz.REMOVED.git-id diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id new file mode 100644 index 00000000..f3692ead --- /dev/null +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +5b0f057a8591d76be009018b302977faeec5159a \ No newline at end of file From 2c831c111021dde35f2ff0c3f94b38296f3fbb68 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 16:03:21 +0100 Subject: [PATCH 16/19] add standalone amlogic grabber fix standalone dispmanx grabber Former-commit-id: 5ace9bc90a6fe76f5a51ecef95d6e7119d1102db --- src/hyperion-aml/AmlogicWrapper.cpp | 38 ++++++++++++++++++ src/hyperion-aml/AmlogicWrapper.h | 43 +++++++++++++++++++++ src/hyperion-aml/CMakeLists.txt | 6 ++- src/hyperion-aml/hyperion-aml.cpp | 38 +++++++++++------- src/hyperion-dispmanx/CMakeLists.txt | 7 +--- src/hyperion-dispmanx/DispmanxWrapper.cpp | 2 +- src/hyperion-dispmanx/DispmanxWrapper.h | 40 +++++++++---------- src/hyperion-dispmanx/hyperion-dispmanx.cpp | 16 ++++---- 8 files changed, 138 insertions(+), 52 deletions(-) create mode 100644 src/hyperion-aml/AmlogicWrapper.cpp create mode 100644 src/hyperion-aml/AmlogicWrapper.h diff --git a/src/hyperion-aml/AmlogicWrapper.cpp b/src/hyperion-aml/AmlogicWrapper.cpp new file mode 100644 index 00000000..e4c1f7f1 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-AmLogic includes +#include "AmlogicWrapper.h" + +AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & AmlogicWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void AmlogicWrapper::start() +{ + _timer.start(); +} + +void AmlogicWrapper::stop() +{ + _timer.stop(); +} + +void AmlogicWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-aml/AmlogicWrapper.h b/src/hyperion-aml/AmlogicWrapper.h new file mode 100644 index 00000000..3f5b0bc8 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.h @@ -0,0 +1,43 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class AmlogicWrapper : public QObject +{ + Q_OBJECT +public: + AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + AmlogicGrabber _grabber; + + // image buffers + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index 5d45222a..cd27c046 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories( ) set(Hyperion_AML_QT_HEADERS + AmlogicWrapper.h ) set(Hyperion_AML_HEADERS @@ -21,12 +22,13 @@ set(Hyperion_AML_HEADERS set(Hyperion_AML_SOURCES hyperion-aml.cpp + AmlogicWrapper.cpp ) if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) endif(ENABLE_QT5) add_executable(hyperion-amlogic diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 71bcd495..cca5e688 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,16 +7,16 @@ // getoptPlusPLus includes #include -#include +#include +#include "AmlogicWrapper.h" using namespace vlofgren; // save the image as screenshot -void saveScreenshot(const char * filename, const Image & image) +void saveScreenshot(const char * filename, const Image & image) { // store as PNG QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); - pngImage = pngImage.rgbSwapped(); pngImage.save(filename); } @@ -30,16 +30,17 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - //IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default=128]"); IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default=128]"); SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - //SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); // set defaults + argFps.setDefault(10); argWidth.setDefault(160); argHeight.setDefault(160); argAddress.setDefault("127.0.0.1:19445"); @@ -57,29 +58,36 @@ int main(int argc, char ** argv) int width = argWidth.getValue(); int height = argHeight.getValue(); - if (width < 160 || height < 60) + if (width < 160 || height < 160) { std::cout << "Minimum width and height is 160" << std::endl; width = std::max(160, width); height = std::max(160, height); } + + int grabInterval = 1000 / argFps.getValue(); + AmlogicWrapper amlWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + if (argScreenshot.isSet()) { - - // Create the grabber - AmlogicGrabber amlGrabber(width, height); - // Capture a single screenshot and finish - Image screenshot; - amlGrabber.grabFrame(screenshot); + const Image & screenshot = amlWrapper.getScreenshot(); saveScreenshot("screenshot.png", screenshot); } else { - // TODO[TvdZ]: Implement the proto-client mechanisme - std::cerr << "The PROTO-interface has not been implemented yet" << std::endl; - } + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + // Connect the screen capturing to the proto processing + QObject::connect(&amlWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + amlWrapper.start(); + + // Start the application + app.exec(); + } } catch (const std::runtime_error & e) { diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 4d48174e..130cb661 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -12,12 +12,7 @@ else(ENABLE_QT5) endif(ENABLE_QT5) # Find the BCM-package (VC control) -#find_package(BCM REQUIRED) -SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) -SET( BCM_LIBRARIES "" ) -ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) - - +find_package(BCM REQUIRED) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index b11830a7..7d8702d2 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -1,5 +1,5 @@ -// Hyperion-X11 includes +// Hyperion-Dispmanx includes #include "DispmanxWrapper.h" DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index 827a4d53..e8526b02 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -7,36 +7,36 @@ class DispmanxWrapper : public QObject { - Q_OBJECT + Q_OBJECT public: - DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); - const Image & getScreenshot(); + const Image & getScreenshot(); - /// - /// Starts the timed capturing of screenshots - /// - void start(); + /// + /// Starts the timed capturing of screenshots + /// + void start(); - void stop(); + void stop(); signals: - void sig_screenshot(const Image & screenshot); + void sig_screenshot(const Image & screenshot); private slots: - /// - /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot - /// signal. - /// - void capture(); + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); private: - /// The QT timer to generate capture-publish events - QTimer _timer; + /// The QT timer to generate capture-publish events + QTimer _timer; - /// The grabber for creating screenshots - DispmanxFrameGrabber _grabber; - Image _screenshot_rgb; - Image _screenshot; + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; }; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index c7d5fe0e..abf78c8c 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -6,7 +6,7 @@ // getoptPlusPLus includes #include -#include "protoserver/ProtoConnectionWrapper.h" +#include #include "DispmanxWrapper.h" using namespace vlofgren; @@ -81,12 +81,12 @@ int main(int argc, char ** argv) app.exec(); } } - catch (const std::runtime_error & e) - { - // An error occured. Display error and quit - std::cerr << e.what() << std::endl; - return -1; - } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } - return 0; + return 0; } From 878538eb50f573658a21bad99a80db8e4e10662e Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 23:34:47 +0100 Subject: [PATCH 17/19] fix compile on raspi Former-commit-id: f526a9facebe8027f6bf50b1e54ab21bc1534faa --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 1004b8ed..77dcb6b7 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From ea89a85ddb87361ccd19ed520861f07f53713dc1 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 25 Feb 2016 15:21:25 +0100 Subject: [PATCH 18/19] make protoconnection to invalid host less blocking Former-commit-id: e7a89c87b15fbe9809ec63468b59ecc55c6d3e72 --- include/protoserver/ProtoConnection.h | 14 +++++++-- libsrc/protoserver/ProtoConnection.cpp | 40 +++++++++++++++++++++----- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index a61947fe..7ecd8f36 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -7,6 +7,7 @@ #include #include #include +#include #include // hyperion util @@ -19,8 +20,11 @@ /// /// Connection class to setup an connection to the hyperion server and execute commands /// -class ProtoConnection +class ProtoConnection : public QObject { + +Q_OBJECT + public: /// /// Constructor @@ -74,10 +78,13 @@ public: /// void sendMessage(const proto::HyperionRequest & message); -private: +private slots: /// Try to connect to the Hyperion host void connectToHost(); + +private: + /// /// Parse a reply message /// @@ -99,4 +106,7 @@ private: /// Skip receiving reply messages from Hyperion if set bool _skipReply; + + QTimer _timer; + QAbstractSocket::SocketState _prevSocketState; }; diff --git a/libsrc/protoserver/ProtoConnection.cpp b/libsrc/protoserver/ProtoConnection.cpp index d7a6037e..5eb5e53c 100644 --- a/libsrc/protoserver/ProtoConnection.cpp +++ b/libsrc/protoserver/ProtoConnection.cpp @@ -9,7 +9,8 @@ ProtoConnection::ProtoConnection(const std::string & a) : _socket(), - _skipReply(false) + _skipReply(false), + _prevSocketState(QAbstractSocket::UnconnectedState) { QString address(a.c_str()); QStringList parts = address.split(":"); @@ -29,10 +30,18 @@ ProtoConnection::ProtoConnection(const std::string & a) : // try to connect to host std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; connectToHost(); + + // start the connection timer + _timer.setInterval(5000); + _timer.setSingleShot(false); + + connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); + _timer.start(); } ProtoConnection::~ProtoConnection() { + _timer.stop(); _socket.close(); } @@ -91,20 +100,37 @@ void ProtoConnection::clearAll() void ProtoConnection::connectToHost() { - _socket.connectToHost(_host, _port); - if (_socket.waitForConnected()) { - std::cout << "Connected to Hyperion host" << std::endl; + // try connection only when + if (_socket.state() == QAbstractSocket::UnconnectedState) + { + _socket.connectToHost(_host, _port); + //_socket.waitForConnected(1000); } } void ProtoConnection::sendMessage(const proto::HyperionRequest &message) { - if (_socket.state() == QAbstractSocket::UnconnectedState) + // print out connection message only when state is changed + if (_socket.state() != _prevSocketState ) { - std::cout << "Currently disconnected: trying to connect to host" << std::endl; - connectToHost(); + switch (_socket.state() ) + { + case QAbstractSocket::UnconnectedState: + std::cout << "No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + case QAbstractSocket::ConnectedState: + std::cout << "Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + default: + //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + } + _prevSocketState = _socket.state(); } + if (_socket.state() != QAbstractSocket::ConnectedState) { return; From f0c1e63fba17cfe99211202972cdb15ca0aed48d Mon Sep 17 00:00:00 2001 From: redpanther Date: Sat, 27 Feb 2016 18:06:04 +0100 Subject: [PATCH 19/19] update compile howto for making release binaries Former-commit-id: 5105b3f374221e573290c98990c55f0bd67ba849 --- CompileHowto.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CompileHowto.txt b/CompileHowto.txt index 621cf8fd..9f419709 100644 --- a/CompileHowto.txt +++ b/CompileHowto.txt @@ -24,11 +24,11 @@ mkdir "$HYPERION_DIR/build" cd "$HYPERION_DIR/build" # run cmake to generate make files on the raspberry pi -cmake .. +cmake -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # or if you are not compiling on the raspberry pi and need to disable the Dispmanx grabber and support for spi devices -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # for OSX build you need XCode, qt4 libraries and cmake. You can use macport (homebrew might work too) to install them sudo port install qt4-mac sudo port install cmake @@ -36,6 +36,12 @@ cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=O # run make to build Hyperion make +# or if you have a system with more then 1 cpu core +make -j 4 +# "4" is the number of cpu cores (e.g. 4 on RPi2), this makes compile faster + +#after compile, to remove any stuff not needed for a release version. +strip bin/* # The binaries are build in "$HYPERION_DIR/build/bin". You could copy those to /usr/bin sudo cp ./bin/hyperion-remote /usr/bin/