From 7352ff4d42883bce4f388b0bccb00d2cc4c08170 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Tue, 1 Jan 2019 19:47:07 +0100 Subject: [PATCH] Threading and more - webui remove restarts - threading for LedDevice --- assets/webconfig/js/content_index.js | 53 ++----- assets/webconfig/js/content_remote.js | 10 +- assets/webconfig/js/hyperion.js | 8 +- assets/webconfig/js/ui_utils.js | 4 +- assets/webconfig/js/wizard.js | 10 +- include/hyperion/GrabberWrapper.h | 3 +- include/hyperion/Hyperion.h | 26 +-- include/leddevice/LedDevice.h | 53 ++++--- include/leddevice/LedDeviceWrapper.h | 111 +++++++++++++ include/utils/GlobalSignals.h | 41 +++++ libsrc/api/JsonAPI.cpp | 9 +- libsrc/hyperion/CaptureCont.cpp | 14 +- libsrc/hyperion/GrabberWrapper.cpp | 8 + libsrc/hyperion/Hyperion.cpp | 61 +++----- libsrc/hyperion/LinearColorSmoothing.cpp | 28 +--- libsrc/hyperion/LinearColorSmoothing.h | 15 +- libsrc/leddevice/LedDevice.cpp | 63 +------- libsrc/leddevice/LedDeviceFactory.cpp | 14 +- libsrc/leddevice/LedDeviceWrapper.cpp | 148 ++++++++++++++++++ .../leddevice/dev_net/LedDevicePhilipsHue.cpp | 30 ++-- .../leddevice/dev_net/LedDevicePhilipsHue.h | 10 +- .../dev_tinker/LedDeviceTinkerforge.cpp | 21 +-- src/hyperiond/hyperiond.cpp | 14 +- src/hyperiond/hyperiond.h | 10 -- 24 files changed, 482 insertions(+), 282 deletions(-) create mode 100644 include/leddevice/LedDeviceWrapper.h create mode 100644 include/utils/GlobalSignals.h create mode 100644 libsrc/leddevice/LedDeviceWrapper.cpp diff --git a/assets/webconfig/js/content_index.js b/assets/webconfig/js/content_index.js index bdec03c3..d0f6ae05 100644 --- a/assets/webconfig/js/content_index.js +++ b/assets/webconfig/js/content_index.js @@ -1,5 +1,4 @@ $(document).ready( function() { - var uiLock = false; loadContentTo("#container_connection_lost","connection_lost"); loadContentTo("#container_restart","restart"); @@ -7,42 +6,26 @@ $(document).ready( function() { $(hyperion).on("cmd-serverinfo",function(event){ serverInfo = event.response.info; - // protect components from serverinfo updates - if(!compsInited) - { - comps = event.response.info.components - compsInited = true; - } + // comps + comps = event.response.info.components - if(!priosInited) - { - priosInited = true; - } $(hyperion).trigger("ready"); - if (serverInfo.hyperion.config_modified) - $("#hyperion_reload_notify").fadeIn("fast"); - else - $("#hyperion_reload_notify").fadeOut("fast"); + comps.forEach( function(obj) { + if (obj.name == "ALL") + { + if(obj.enabled) + $("#hyperion_disabled_notify").fadeOut("fast"); + else + $("#hyperion_disabled_notify").fadeIn("fast"); + } + }); if (serverInfo.hyperion.enabled) $("#hyperion_disabled_notify").fadeOut("fast"); else $("#hyperion_disabled_notify").fadeIn("fast"); - if (!serverInfo.hyperion.config_writeable) - { - showInfoDialog('uilock',$.i18n('InfoDialog_nowrite_title'),$.i18n('InfoDialog_nowrite_text')); - $('#wrapper').toggle(false); - uiLock = true; - } - else if (uiLock) - { - $("#modal_dialog").modal('hide'); - $('#wrapper').toggle(true); - uiLock = false; - } - updateSessions(); }); // end cmd-serverinfo @@ -51,21 +34,21 @@ $(document).ready( function() { updateSessions(); }); - $(hyperion).one("cmd-sysinfo", function(event) { + $(hyperion).on("cmd-sysinfo", function(event) { requestServerInfo(); sysInfo = event.response.info; currentVersion = sysInfo.hyperion.version; }); - $(hyperion).one("cmd-config-getschema", function(event) { + $(hyperion).on("cmd-config-getschema", function(event) { serverSchema = event.response.info; requestServerConfig(); schema = serverSchema.properties; }); - $(hyperion).one("cmd-config-getconfig", function(event) { + $(hyperion).on("cmd-config-getconfig", function(event) { serverConfig = event.response.info; requestSysInfo(); @@ -80,7 +63,7 @@ $(document).ready( function() { requestServerConfigSchema(); }); - $(hyperion).one("ready", function(event) { + $(hyperion).on("ready", function(event) { loadContent(); }); @@ -98,7 +81,7 @@ $(document).ready( function() { // notfication in index if (obj.name == "ALL") { - if(obj.enable) + if(obj.enabled) $("#hyperion_disabled_notify").fadeOut("fast"); else $("#hyperion_disabled_notify").fadeIn("fast"); @@ -117,10 +100,6 @@ $(document).ready( function() { serverInfo.effects = event.response.data.effects }); - $("#btn_hyperion_reload").on("click", function(){ - initRestart(); - }); - $(".mnava").bind('click.menu', function(e){ loadContent(e); window.scrollTo(0, 0); diff --git a/assets/webconfig/js/content_remote.js b/assets/webconfig/js/content_remote.js index fde23d4f..eab3dca6 100644 --- a/assets/webconfig/js/content_remote.js +++ b/assets/webconfig/js/content_remote.js @@ -203,6 +203,14 @@ $(document).ready(function() { function updateComponents() { components = comps; + var hyperionEnabled = true; + components.forEach( function(obj) { + if (obj.name == "ALL") + { + hyperionEnabled = obj.enabled + } + }); + // create buttons $('#componentsbutton').html(""); for ( idx=0; idx
'+$.i18n('edt_append_s')+'
'); $('#wizp2_body').append(''); $('#wizp2_body').append('
'); - $('#wizp2_footer').html('') + $('#wizp2_footer').html('') //open modal $("#wizard_modal").modal({ @@ -155,7 +155,6 @@ resetWizard(); serverConfig.device.colorOrder = new_rgb_order; requestWriteConfig({"device" : serverConfig.device}); - setTimeout(initRestart, 100); }); } @@ -416,7 +415,7 @@ $('#wizp1_body').html('

'+$.i18n('wiz_cc_title')+'

'+$.i18n('wiz_cc_intro1')+'

'); $('#wizp1_footer').html(''); $('#wizp2_body').html('
'); - $('#wizp2_footer').html('') + $('#wizp2_footer').html('') //open modal $("#wizard_modal").modal({ @@ -500,7 +499,6 @@ $('#btn_wiz_save').off().on('click',function() { requestWriteConfig(wiz_editor.getValue()); resetWizard(); - setTimeout(initRestart, 200); }); wiz_editor.on("change", function(e){ @@ -538,7 +536,7 @@ $('#wizp2_body').append(''); createTable("lidsh", "lidsb", "hue_ids_t"); $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'),$.i18n('wiz_hue_pos'),$.i18n('wiz_hue_ident')], true)); - $('#wizp2_footer').html(''); + $('#wizp2_footer').html(''); $('#wizp3_body').html(''+$.i18n('wiz_hue_press_link')+'


'); //open modal @@ -751,7 +749,7 @@ serverConfig.smoothing.enable = false; requestWriteConfig(serverConfig, true); - setTimeout(initRestart,200); + resetWizard(); }); $('#btn_wiz_abort').off().on('click', resetWizard); diff --git a/include/hyperion/GrabberWrapper.h b/include/hyperion/GrabberWrapper.h index 2fc45f48..57c92808 100644 --- a/include/hyperion/GrabberWrapper.h +++ b/include/hyperion/GrabberWrapper.h @@ -14,7 +14,7 @@ #include class Grabber; -class DispmanxFrameGrabber; +class GlobalSignals; class QTimer; /// @@ -60,7 +60,6 @@ public: return false; } - public slots: /// /// virtual method, should perform single frame grab and computes the led-colors diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 9bb9a569..c79d6237 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -5,7 +5,7 @@ #include // QT includes -#include +//#include #include #include #include @@ -37,11 +37,9 @@ // Forward class declaration class QTimer; - class HyperionDaemon; class ImageProcessor; class MessageForwarder; -class LedDevice; class LinearColorSmoothing; class EffectEngine; class MultiColorAdjustment; @@ -50,6 +48,7 @@ class SettingsManager; class BGEffectHandler; class CaptureCont; class BoblightServer; +class LedDeviceWrapper; /// /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through @@ -228,6 +227,13 @@ public: /// @return the state bool sourceAutoSelectEnabled(); + /// + /// @brief Called from components to update their current state. DO NOT CALL FROM USERS + /// @param[in] component The component from enum + /// @param[in] state The state of the component [true | false] + /// + void setNewComponentState(const hyperion::Components& component, const bool& state); + /// /// @brief Enable/Disable components during runtime, called from external API (requests) /// @@ -432,13 +438,9 @@ signals: void effectListUpdated(); /// - /// @brief systemImage from the parent HyperionDaemon SystemCapture + /// @brief Emits whenever new data should be pushed to the LedDeviceWrapper which forwards it to the threaded LedDevice /// - void systemImage(const Image& image); - /// - /// @brief v4lImage from the parent HyperionDaemon V4lCapture - /// - void v4lImage(const Image & image); + void ledDeviceData(const std::vector& ledValues); /// /// @brief Emits whenever new untransformed ledColos data is available, reflects the current visible device @@ -504,8 +506,8 @@ private: /// The adjustment from raw colors to led colors MultiColorAdjustment * _raw2ledAdjustment; - /// The actual LedDevice - LedDevice * _device; + /// The actual LedDeviceWrapper + LedDeviceWrapper* _ledDeviceWrapper; /// The smoothing LedDevice LinearColorSmoothing * _deviceSmooth; @@ -513,7 +515,7 @@ private: /// Effect engine EffectEngine * _effectEngine; - // proto and json Message forwarder + // Message forwarder MessageForwarder * _messageForwarder; /// the name of config file diff --git a/include/leddevice/LedDevice.h b/include/leddevice/LedDevice.h index 8b9977e2..485f537c 100644 --- a/include/leddevice/LedDevice.h +++ b/include/leddevice/LedDevice.h @@ -34,11 +34,8 @@ class LedDevice : public QObject Q_OBJECT public: - LedDevice(); - /// - /// Empty virtual destructor for pure virtual base class - /// - virtual ~LedDevice() {} + LedDevice(const QJsonObject& config = QJsonObject(), QObject* parent = nullptr); + virtual ~LedDevice(); /// Switch the leds off (led hardware disable) virtual int switchOff(); @@ -48,33 +45,38 @@ public: virtual int setLedValues(const std::vector& ledValues); - /// - /// Opens and configures the output device - /// - /// @return Zero on succes else negative - /// - virtual int open(); - /// /// @brief Get color order of device /// @return The color order /// const QString & getColorOrder() { return _colorOrder; }; - static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr); - static const LedDeviceRegistry& getDeviceMap(); void setActiveDevice(QString dev); const QString & getActiveDevice() { return _activeDevice; }; - static QJsonObject getLedDeviceSchemas(); void setLedCount(int ledCount); int getLedCount() { return _ledCount; } void setEnable(bool enable); bool enabled() { return _enabled; }; - int getLatchTime() { return _latchTime_ms; }; + const int getLatchTime() { return _latchTime_ms; }; inline bool componentState() { return enabled(); }; +public slots: + /// + /// Is called on thread start, all construction tasks and init should run here + /// + virtual void start() { _deviceReady = open(); }; + + /// + /// Writes the RGB-Color values to the leds. + /// + /// @param[in] ledValues The RGB-color per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector& ledValues) = 0; + signals: /// /// Emits whenever the led device switches between on/off @@ -83,16 +85,18 @@ signals: void enableStateChanged(bool newState); protected: - /// - /// Writes the RGB-Color values to the leds. - /// - /// @param[in] ledValues The RGB-color per led - /// - /// @return Zero on success else negative - /// - virtual int write(const std::vector& ledValues) = 0; virtual bool init(const QJsonObject &deviceConfig); + /// + /// Opens and configures the output device + /// + /// @return Zero on succes else negative + /// + virtual int open(); + + // Helper to pipe device config from constructor to start() + QJsonObject _devConfig; + /// The common Logger instance for all LedDevices Logger * _log; @@ -102,7 +106,6 @@ protected: bool _deviceReady; QString _activeDevice; - static LedDeviceRegistry _ledDeviceMap; int _ledCount; int _ledRGBCount; diff --git a/include/leddevice/LedDeviceWrapper.h b/include/leddevice/LedDeviceWrapper.h new file mode 100644 index 00000000..b3cb9271 --- /dev/null +++ b/include/leddevice/LedDeviceWrapper.h @@ -0,0 +1,111 @@ +#pragma once + +// util +#include +#include +#include + +class LedDevice; +class Hyperion; + +typedef LedDevice* ( *LedDeviceCreateFuncType ) ( const QJsonObject& ); +typedef std::map LedDeviceRegistry; + +/// +/// @brief Creates and destroys LedDevice instances with LedDeviceFactory and moves the device to a thread. Pipes all signal/slots and methods to LedDevice instance +/// +class LedDeviceWrapper : public QObject +{ + Q_OBJECT +public: + LedDeviceWrapper(Hyperion* hyperion); + ~LedDeviceWrapper(); + /// + /// @brief Contructs a new LedDevice, moves to thread and starts + /// @param config With the given config + /// + void createLedDevice(const QJsonObject& config); + + /// + /// @brief Get all available device schemas + /// @return device schemas + /// + static const QJsonObject getLedDeviceSchemas(); + + /// + /// @brief add all device constrcutors to the map + /// + static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr); + + /// + /// @brief Return all available device contructors + /// @return device constrcutors + /// + static const LedDeviceRegistry& getDeviceMap(); + + /// + /// @brief Get the current latchtime of the ledDevice + /// @ return latchtime in ms + /// + int getLatchTime(); + + /// + /// @brief Get the current active ledDevice + /// + const QString & getActiveDevice(); + + /// + /// @brief Return the last enable state + /// + const bool & enabled() { return _enabled; }; + + /// + /// @brief Get the current colorOrder from device + /// + const QString & getColorOrder(); + +public slots: + /// + /// @brief Handle new component state request + /// @apram component The comp from enum + /// @param state The new state + /// + void handleComponentState(const hyperion::Components component, const bool state); + +signals: + /// + /// PIPER signal for Hyperion -> LedDevice + /// + /// @param[in] ledValues The RGB-color per led + /// + /// @return Zero on success else negative + /// + int write(const std::vector& ledValues); + +private slots: + /// + /// @brief Is called whenever the led device switches between on/off. The led device can disable it's component state + /// The signal comes from the LedDevice + /// @param newState The new state of the device + /// + void handleInternalEnableState(bool newState); + + +protected: + /// contains all available led device constrcutors + static LedDeviceRegistry _ledDeviceMap; + +private: + /// + /// @brief switchOff() the device and Stops the device thread + /// + void stopDeviceThread(); + +private: + // parent Hyperion + Hyperion* _hyperion; + // Pointer of current led device + LedDevice* _ledDevice; + // the enable state + bool _enabled; +}; diff --git a/include/utils/GlobalSignals.h b/include/utils/GlobalSignals.h new file mode 100644 index 00000000..e3fd8efd --- /dev/null +++ b/include/utils/GlobalSignals.h @@ -0,0 +1,41 @@ +#pragma once + +// util +#include +#include + +// qt +#include + +/// +/// Singleton instance for simple signal sharing across threads, should be never used with Qt:DirectConnection! +/// +class GlobalSignals : public QObject +{ + Q_OBJECT +public: + static GlobalSignals* getInstance() + { + static GlobalSignals instance; + return & instance; + } +private: + GlobalSignals() {} + +public: + GlobalSignals(GlobalSignals const&) = delete; + void operator=(GlobalSignals const&) = delete; + +signals: + /// + /// @brief PIPE SystemCapture images from GrabberWrapper to Hyperion class + /// @param image The prepared image + /// + void setSystemImage(const Image& image); + + /// + /// @brief PIPE v4lCapture images from v4lCapture over HyperionDaemon to Hyperion class + /// @param image The prepared image + /// + void setV4lImage(const Image & image); +}; diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index fcbfb7d3..42101d78 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,6 +50,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe , _image_stream_timeout(0) , _led_stream_timeout(0) { + Q_INIT_RESOURCE(JSONRPC_schemas); + // the JsonCB creates json messages you can subscribe to e.g. data change events; forward them to the parent client connect(_jsonCB, &JsonCB::newCallback, this, &JsonAPI::callbackMessage); @@ -63,7 +65,6 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe void JsonAPI::handleMessage(const QString& messageString) { const QString ident = "JsonRpc@"+_peerAddress; - Q_INIT_RESOURCE(JSONRPC_schemas); QJsonObject message; // parse the message if(!JsonUtils::parse(ident, messageString, message, _log)) @@ -408,7 +409,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject& message, const QString& QJsonObject ledDevices; ledDevices["active"] = _hyperion->getActiveDevice(); QJsonArray availableLedDevices; - for (auto dev: LedDevice::getDeviceMap()) + for (auto dev: LedDeviceWrapper::getDeviceMap()) { availableLedDevices.append(dev.first); } @@ -696,7 +697,7 @@ void JsonAPI::handleSchemaGetCommand(const QJsonObject& message, const QString& // collect all LED Devices properties = schemaJson["properties"].toObject(); - alldevices = LedDevice::getLedDeviceSchemas(); + alldevices = LedDeviceWrapper::getLedDeviceSchemas(); properties.insert("alldevices", alldevices); // collect all available effect schemas diff --git a/libsrc/hyperion/CaptureCont.cpp b/libsrc/hyperion/CaptureCont.cpp index 71baa73c..db26931f 100644 --- a/libsrc/hyperion/CaptureCont.cpp +++ b/libsrc/hyperion/CaptureCont.cpp @@ -1,6 +1,12 @@ #include +// hyperion includes #include + +// utils includes +#include + +// qt includes #include CaptureCont::CaptureCont(Hyperion* hyperion) @@ -56,11 +62,11 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable) if(enable) { _hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER); - connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage); + connect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, this, &CaptureCont::handleSystemImage); } else { - disconnect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage); + disconnect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, 0, 0); _hyperion->clear(_systemCaptPrio); } _systemCaptEnabled = enable; @@ -75,11 +81,11 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable) if(enable) { _hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L); - connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); + connect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, this, &CaptureCont::handleV4lImage); } else { - disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); + disconnect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, 0, 0); _hyperion->clear(_v4lCaptPrio); _v4lInactiveTimer->stop(); } diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index d41bd35e..0f1bc959 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -3,6 +3,9 @@ #include #include +// utils includes +#include + // qt #include @@ -20,6 +23,11 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned _image.resize(width, height); connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action); + + // connect the image forwarding + _grabberName.startsWith("V4L") + ? connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setV4lImage) + : connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setSystemImage); } GrabberWrapper::~GrabberWrapper() diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index c38bc916..0fb7b1d8 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -26,8 +26,7 @@ #include // Leddevice includes -#include -#include +#include #include #include "LinearColorSmoothing.h" @@ -127,22 +126,23 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString QJsonObject ledDevice = getSetting(settings::DEVICE).object(); ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info - _device = LedDeviceFactory::construct(ledDevice); - _deviceSmooth = new LinearColorSmoothing(_device, getSetting(settings::SMOOTHING), this); + _ledDeviceWrapper = new LedDeviceWrapper(this); + connect(this, &Hyperion::componentStateChanged, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState); + connect(this, &Hyperion::ledDeviceData, _ledDeviceWrapper, &LedDeviceWrapper::write); + _ledDeviceWrapper->createLedDevice(ledDevice); + + // smoothing + _deviceSmooth = new LinearColorSmoothing(getSetting(settings::SMOOTHING), this); connect(this, &Hyperion::settingsChanged, _deviceSmooth, &LinearColorSmoothing::handleSettingsUpdate); - getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); - - // create the effect engine and pipe the updateEmit; must be initialized after smoothing! + // create the effect engine; needs to be initialized after smoothing! _effectEngine = new EffectEngine(this); connect(_effectEngine, &EffectEngine::effectListUpdated, this, &Hyperion::effectListUpdated); // setup config state checks and initial shot checkConfigState(); if(_fsWatcher.addPath(_configFile)) - { QObject::connect(&_fsWatcher, &QFileSystemWatcher::fileChanged, this, &Hyperion::checkConfigState); - } else { _cTimer = new QTimer(this); @@ -153,6 +153,7 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString // initial startup effect hyperion::handleInitialEffect(this, getSetting(settings::FGEFFECT).object()); + // handle background effect _BGEffectHandler = new BGEffectHandler(this); @@ -163,7 +164,6 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString 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); } @@ -188,10 +188,10 @@ void Hyperion::freeObjects(bool emitCloseSignal) delete _captureCont; delete _effectEngine; //delete _deviceSmooth; - delete _device; delete _raw2ledAdjustment; delete _messageForwarder; delete _settingsManager; + delete _ledDeviceWrapper; } void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) @@ -241,7 +241,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum _hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount()); // update led count in device - _device->setLedCount(_hwLedCount); + //_ledDeviceWrapper->setLedCount(_hwLedCount); // change in leds are also reflected in adjustment delete _raw2ledAdjustment; @@ -262,7 +262,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum _hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount()); // force ledString update, if device ByteOrder changed - if(_device->getColorOrder() != dev["colorOrder"].toString("rgb")) + if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb")) { _ledString = hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev)); _ledStringClone = hyperion::createLedStringClone(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev)); @@ -276,16 +276,9 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum // update led count _device->setLedCount(_hwLedCount); */ - // do always reinit - // TODO segfaulting in LinearColorSmoothing::queueColor triggert from QTimer because of device->setLEdValues (results from gdb debugging and testing) - bool wasEnabled = _deviceSmooth->enabled(); - _deviceSmooth->stopTimer(); - delete _device; + // do always reinit until the led devices can handle dynamic changes dev["currentLedCount"] = int(_hwLedCount); // Inject led count info - _device = LedDeviceFactory::construct(dev); - getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); - if(wasEnabled) - _deviceSmooth->startTimerDelayed(); + _ledDeviceWrapper->createLedDevice(dev); _lockUpdate = false; } // update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer color @@ -310,7 +303,7 @@ QString Hyperion::getConfigFileName() const int Hyperion::getLatchTime() const { - return _device->getLatchTime(); + return _ledDeviceWrapper->getLatchTime(); } unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz, unsigned updateDelay) @@ -373,18 +366,14 @@ bool Hyperion::sourceAutoSelectEnabled() return _muxer.isSourceAutoSelectEnabled(); } +void Hyperion::setNewComponentState(const hyperion::Components& component, const bool& state) +{ + _componentRegister.componentStateChanged(component, state); +} + void Hyperion::setComponentState(const hyperion::Components component, const bool state) { - switch (component) - { - case hyperion::COMP_LEDDEVICE: - _device->setEnable(state); - getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); - break; - - default: - emit componentStateChanged(component, state); - } + emit componentStateChanged(component, state); } void Hyperion::registerInput(const int priority, const hyperion::Components& component, const QString& origin, const QString& owner, unsigned smooth_cfg) @@ -571,7 +560,7 @@ const VideoMode & Hyperion::getCurrentVideoMode() const QString & Hyperion::getActiveDevice() { - return _device->getActiveDevice(); + return _ledDeviceWrapper->getActiveDevice(); } void Hyperion::updatedComponentState(const hyperion::Components comp, const bool state) @@ -681,7 +670,7 @@ void Hyperion::update() } // Write the data to the device - if (_device->enabled()) + if (_ledDeviceWrapper->enabled()) { _deviceSmooth->selectConfig(priorityInfo.smooth_cfg); @@ -690,6 +679,6 @@ void Hyperion::update() _deviceSmooth->setLedValues(_ledBuffer); if (! _deviceSmooth->enabled()) - _device->setLedValues(_ledBuffer); + emit ledDeviceData(_ledBuffer); } } diff --git a/libsrc/hyperion/LinearColorSmoothing.cpp b/libsrc/hyperion/LinearColorSmoothing.cpp index 2cd73b88..47bafe45 100644 --- a/libsrc/hyperion/LinearColorSmoothing.cpp +++ b/libsrc/hyperion/LinearColorSmoothing.cpp @@ -9,9 +9,8 @@ using namespace hyperion; -LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDocument& config, Hyperion* hyperion) - : LedDevice() - , _ledDevice(ledDevice) +LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion) + : LedDevice(QJsonObject(), hyperion) , _log(Logger::getInstance("SMOOTHING")) , _hyperion(hyperion) , _updateInterval(1000) @@ -42,8 +41,7 @@ LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDo LinearColorSmoothing::~LinearColorSmoothing() { - // Make sure to switch off the underlying led-device (because switchOff is no longer forwarded) - _ledDevice->switchOff(); + } void LinearColorSmoothing::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) @@ -148,7 +146,8 @@ void LinearColorSmoothing::queueColors(const std::vector & ledColors) { // No output delay => immediate write if ( _writeToLedsEnable && !_pause) - _ledDevice->setLedValues(ledColors); + emit _hyperion->ledDeviceData(ledColors); + } else { @@ -163,7 +162,7 @@ void LinearColorSmoothing::queueColors(const std::vector & ledColors) { if (!_pause) { - _ledDevice->setLedValues(_outputQueue.front()); + emit _hyperion->ledDeviceData(_outputQueue.front()); } _outputQueue.pop_front(); } @@ -235,18 +234,3 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force) _currentConfigId = 0; return false; } - -void LinearColorSmoothing::startTimerDelayed() -{ - QTimer::singleShot(500, this, SLOT(delayStartTimer())); -} - -void LinearColorSmoothing::stopTimer() -{ - _timer->stop(); -} - -void LinearColorSmoothing::delayStartTimer() -{ - _timer->start(); -} diff --git a/libsrc/hyperion/LinearColorSmoothing.h b/libsrc/hyperion/LinearColorSmoothing.h index 97bb846c..e84b0384 100644 --- a/libsrc/hyperion/LinearColorSmoothing.h +++ b/libsrc/hyperion/LinearColorSmoothing.h @@ -28,11 +28,10 @@ class LinearColorSmoothing : public LedDevice public: /// Constructor - /// @param LedDevice the led device /// @param config The configuration document smoothing /// @param hyperion The hyperion parent instance /// - LinearColorSmoothing(LedDevice *ledDevice, const QJsonDocument& config, Hyperion* hyperion); + LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion); /// Destructor virtual ~LinearColorSmoothing(); @@ -71,12 +70,6 @@ public: /// bool selectConfig(unsigned cfg, const bool& force = false); - /// - /// @ Helper methods to start the timer with delay (see delayStartSmooth()) - /// - void startTimerDelayed(); - void stopTimer(); - public slots: /// /// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor @@ -89,9 +82,6 @@ private slots: /// Timer callback which writes updated led values to the led device void updateLeds(); - /// Delay timer slot to workaround the leddevice reconstruction segfault (dangling pointer) - void delayStartTimer(); - /// /// @brief Handle component state changes /// @param component The component @@ -107,9 +97,6 @@ private: */ void queueColors(const std::vector & ledColors); - /// The led device - LedDevice * _ledDevice; - /// Logger instance Logger* _log; diff --git a/libsrc/leddevice/LedDevice.cpp b/libsrc/leddevice/LedDevice.cpp index b8daccc8..45331853 100644 --- a/libsrc/leddevice/LedDevice.cpp +++ b/libsrc/leddevice/LedDevice.cpp @@ -10,10 +10,9 @@ #include "hyperion/Hyperion.h" #include -LedDeviceRegistry LedDevice::_ledDeviceMap = LedDeviceRegistry(); - -LedDevice::LedDevice() - : QObject() +LedDevice::LedDevice(const QJsonObject& config, QObject* parent) + : QObject(parent) + , _devConfig(config) , _log(Logger::getInstance("LEDDEVICE")) , _ledBuffer(0) , _deviceReady(true) @@ -24,15 +23,16 @@ LedDevice::LedDevice() , _componentRegistered(false) , _enabled(true) { - LedDevice::getLedDeviceSchemas(); - qRegisterMetaType("hyperion::Components"); - // setup timer - _refresh_timer.setSingleShot(false); _refresh_timer.setInterval(0); connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds())); } +LedDevice::~LedDevice() +{ + +} + // dummy implemention int LedDevice::open() { @@ -55,17 +55,6 @@ void LedDevice::setEnable(bool enable) _enabled = enable; } -int LedDevice::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr) -{ - _ledDeviceMap.emplace(name,funcPtr); - return 0; -} - -const LedDeviceRegistry& LedDevice::getDeviceMap() -{ - return _ledDeviceMap; -} - void LedDevice::setActiveDevice(QString dev) { _activeDevice = dev; @@ -88,42 +77,6 @@ bool LedDevice::init(const QJsonObject &deviceConfig) return true; } -QJsonObject LedDevice::getLedDeviceSchemas() -{ - // make sure the resources are loaded (they may be left out after static linking) - Q_INIT_RESOURCE(LedDeviceSchemas); - - // read the json schema from the resource - QDir d(":/leddevices/"); - QStringList l = d.entryList(); - QJsonObject result, schemaJson; - - for(QString &item : l) - { - QString schemaPath(QString(":/leddevices/")+item); - QString devName = item.remove("schema-"); - - QString data; - if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice"))) - { - throw std::runtime_error("ERROR: Schema not found: " + item.toStdString()); - } - - QJsonObject schema; - if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice"))) - { - throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString()); - } - - schemaJson = schema; - schemaJson["title"] = QString("edt_dev_spec_header_title"); - - result[devName] = schemaJson; - } - - return result; -} - int LedDevice::setLedValues(const std::vector& ledValues) { int retval = 0; diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 8deaaf96..0d38c6ce 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -7,10 +7,11 @@ // Leddevice includes #include +#include #include #include -// following file is auto generated by cmake! it contains all available leddevice headers +// autogen #include "LedDevice_headers.h" LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) @@ -21,14 +22,7 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) QString type = deviceConfig["type"].toString("UNSPECIFIED").toLower(); - #define REGISTER(className) LedDevice::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct); - - // the REGISTER() calls are autogenerated by cmake. - #include "LedDevice_register.cpp" - - #undef REGISTER - - const LedDeviceRegistry& devList = LedDevice::getDeviceMap(); + const LedDeviceRegistry& devList = LedDeviceWrapper::getDeviceMap(); LedDevice* device = nullptr; try { @@ -56,7 +50,5 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) device = LedDeviceFile::construct(QJsonObject()); } - device->open(); - return device; } diff --git a/libsrc/leddevice/LedDeviceWrapper.cpp b/libsrc/leddevice/LedDeviceWrapper.cpp new file mode 100644 index 00000000..b067c4d7 --- /dev/null +++ b/libsrc/leddevice/LedDeviceWrapper.cpp @@ -0,0 +1,148 @@ +#include + +#include +#include + +// following file is auto generated by cmake! it contains all available leddevice headers +#include "LedDevice_headers.h" + +// util +#include +#include + +// qt +#include +#include + +LedDeviceRegistry LedDeviceWrapper::_ledDeviceMap = LedDeviceRegistry(); + +LedDeviceWrapper::LedDeviceWrapper(Hyperion* hyperion) + : QObject(hyperion) + , _hyperion(hyperion) + , _ledDevice(nullptr) +{ + // prepare the device constrcutor map + #define REGISTER(className) LedDeviceWrapper::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct); + + // the REGISTER() calls are autogenerated by cmake. + #include "LedDevice_register.cpp" + + #undef REGISTER + + _hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, true); +} + +LedDeviceWrapper::~LedDeviceWrapper() +{ + stopDeviceThread(); +} + +void LedDeviceWrapper::createLedDevice(const QJsonObject& config) +{ + if(_ledDevice != nullptr) + { + stopDeviceThread(); + } + + // create thread and device + QThread* thread = new QThread(this); + _ledDevice = LedDeviceFactory::construct(config); + _ledDevice->moveToThread(thread); + // setup thread management + connect(thread, &QThread::started, _ledDevice, &LedDevice::start); + connect(thread, &QThread::finished, thread, &QObject::deleteLater); + connect(thread, &QThread::finished, _ledDevice, &QObject::deleteLater); + + // further signals + connect(this, &LedDeviceWrapper::write, _ledDevice, &LedDevice::write); + connect(_ledDevice, &LedDevice::enableStateChanged, this, &LedDeviceWrapper::handleInternalEnableState); + + // start the thread + thread->start(); +} + +const QJsonObject LedDeviceWrapper::getLedDeviceSchemas() +{ + // make sure the resources are loaded (they may be left out after static linking) + Q_INIT_RESOURCE(LedDeviceSchemas); + + // read the json schema from the resource + QDir d(":/leddevices/"); + QStringList l = d.entryList(); + QJsonObject result, schemaJson; + + for(QString &item : l) + { + QString schemaPath(QString(":/leddevices/")+item); + QString devName = item.remove("schema-"); + + QString data; + if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice"))) + { + throw std::runtime_error("ERROR: Schema not found: " + item.toStdString()); + } + + QJsonObject schema; + if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice"))) + { + throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString()); + } + + schemaJson = schema; + schemaJson["title"] = QString("edt_dev_spec_header_title"); + + result[devName] = schemaJson; + } + + return result; +} + +int LedDeviceWrapper::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr) +{ + _ledDeviceMap.emplace(name,funcPtr); + return 0; +} + +const LedDeviceRegistry& LedDeviceWrapper::getDeviceMap() +{ + return _ledDeviceMap; +} + +int LedDeviceWrapper::getLatchTime() +{ + return _ledDevice->getLatchTime(); +} + +const QString & LedDeviceWrapper::getActiveDevice() +{ + return _ledDevice->getActiveDevice(); +} + +const QString & LedDeviceWrapper::getColorOrder() +{ + return _ledDevice->getColorOrder(); +} + +void LedDeviceWrapper::handleComponentState(const hyperion::Components component, const bool state) +{ + if(component == hyperion::COMP_LEDDEVICE) + { + _ledDevice->setEnable(state); + _hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, _ledDevice->componentState()); + _enabled = state; + } +} + +void LedDeviceWrapper::handleInternalEnableState(bool newState) +{ + _hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, newState); + _enabled = newState; +} + +void LedDeviceWrapper::stopDeviceThread() +{ + _ledDevice->switchOff(); + QThread* oldThread = _ledDevice->thread(); + delete _ledDevice; // fast desctruction + oldThread->quit(); // non blocking +} diff --git a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp index 1830394b..4a66afa9 100755 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp @@ -201,7 +201,7 @@ void PhilipsHueBridge::resolveReply(QNetworkReply* reply) void PhilipsHueBridge::post(QString route, QString content) { - Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content)); + //Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content)); QNetworkRequest request(QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route)); manager.put(request, content.toLatin1()); @@ -214,7 +214,7 @@ const std::set PhilipsHueLight::GAMUT_B_MODEL_IDS = const std::set PhilipsHueLight::GAMUT_C_MODEL_IDS = { "LLC020", "LST002", "LCT011", "LCT012", "LCT010", "LCT014" }; -PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values) +PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values) : log(log) , bridge(bridge) , id(id) @@ -297,7 +297,7 @@ PhilipsHueLight::~PhilipsHueLight() void PhilipsHueLight::set(QString state) { - bridge.post(QString("lights/%1/state").arg(id), state); + bridge->post(QString("lights/%1/state").arg(id), state); } void PhilipsHueLight::setOn(bool on) @@ -345,18 +345,25 @@ LedDevice* LedDevicePhilipsHue::construct(const QJsonObject &deviceConfig) } LedDevicePhilipsHue::LedDevicePhilipsHue(const QJsonObject& deviceConfig) - : LedDevice() - , bridge(_log, deviceConfig["output"].toString(), deviceConfig["username"].toString()) + : LedDevice(deviceConfig) + , _bridge(nullptr) { - _deviceReady = init(deviceConfig); - connect(&bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights); - connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged); } LedDevicePhilipsHue::~LedDevicePhilipsHue() { switchOff(); + delete _bridge; +} + +void LedDevicePhilipsHue::start() +{ + _bridge = new PhilipsHueBridge(_log, _devConfig["output"].toString(), _devConfig["username"].toString()); + _deviceReady = init(_devConfig); + + connect(_bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights); + connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged); } bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig) @@ -374,7 +381,7 @@ bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig) lightIds.push_back(i.toInt()); } // get light info from bridge - bridge.bConnect(); + _bridge->bConnect(); // adapt latchTime to count of user lightIds (bridge 10Hz max overall) newDC.insert("latchTime",QJsonValue(100*(int)lightIds.size())); @@ -399,7 +406,7 @@ void LedDevicePhilipsHue::newLights(QMap map) { if (map.contains(id)) { - lights.push_back(PhilipsHueLight(_log, bridge, id, map.value(id))); + lights.push_back(PhilipsHueLight(_log, _bridge, id, map.value(id))); } else { @@ -427,7 +434,6 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Get color. ColorRgb color = ledValues.at(idx); - // Scale colors from [0, 255] to [0, 1] and convert to xy space. CiColor xy = CiColor::rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, light.getColorSpace()); @@ -453,7 +459,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) void LedDevicePhilipsHue::stateChanged(bool newState) { if(newState) - bridge.bConnect(); + _bridge->bConnect(); else lights.clear(); } diff --git a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h index cc959ab1..0403b388 100644 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h @@ -139,7 +139,7 @@ class PhilipsHueLight { private: Logger* log; - PhilipsHueBridge& bridge; + PhilipsHueBridge* bridge; /// light id unsigned int id; bool on; @@ -172,7 +172,7 @@ public: /// @param bridge the bridge /// @param id the light id /// - PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values); + PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values); ~PhilipsHueLight(); /// @@ -227,6 +227,10 @@ public: /// constructs leddevice static LedDevice* construct(const QJsonObject &deviceConfig); +public slots: + /// thread start + virtual void start(); + private slots: /// creates new PhilipsHueLight(s) based on user lightid with bridge feedback /// @@ -249,7 +253,7 @@ protected: private: /// bridge class - PhilipsHueBridge bridge; + PhilipsHueBridge* _bridge; /// bool switchOffOnBlack; diff --git a/libsrc/leddevice/dev_tinker/LedDeviceTinkerforge.cpp b/libsrc/leddevice/dev_tinker/LedDeviceTinkerforge.cpp index b0c319ae..d1eac74d 100644 --- a/libsrc/leddevice/dev_tinker/LedDeviceTinkerforge.cpp +++ b/libsrc/leddevice/dev_tinker/LedDeviceTinkerforge.cpp @@ -40,7 +40,7 @@ bool LedDeviceTinkerforge::init(const QJsonObject &deviceConfig) _uid = deviceConfig["uid"].toString(); _interval = deviceConfig["rate"].toInt(); - if ((unsigned)_ledCount > MAX_NUM_LEDS) + if ((unsigned)_ledCount > MAX_NUM_LEDS) { Error(_log,"Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS); return -1; @@ -68,7 +68,7 @@ int LedDeviceTinkerforge::open() if (_ipConnection != nullptr) { Error(_log, "Attempt to open existing connection; close before opening"); - return -1; + return 0; } // Initialise a new connection @@ -76,10 +76,10 @@ int LedDeviceTinkerforge::open() ipcon_create(_ipConnection); int connectionStatus = ipcon_connect(_ipConnection, QSTRING_CSTR(_host), _port); - if (connectionStatus < 0) + if (connectionStatus < 0) { - Warning(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus); - return -1; + Error(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus); + return 0; } // Create the 'LedStrip' @@ -87,17 +87,20 @@ int LedDeviceTinkerforge::open() led_strip_create(_ledStrip, QSTRING_CSTR(_uid), _ipConnection); int frameStatus = led_strip_set_frame_duration(_ledStrip, _interval); - if (frameStatus < 0) + if (frameStatus < 0) { Error(_log,"Attempt to connect to led strip bricklet (led_strip_set_frame_duration()) failed with status %d", frameStatus); - return -1; + return 0; } - return 0; + return 1; } int LedDeviceTinkerforge::write(const std::vector &ledValues) { + if(!_deviceReady) + return 0; + auto redIt = _redChannel.begin(); auto greenIt = _greenChannel.begin(); auto blueIt = _blueChannel.begin(); @@ -115,7 +118,7 @@ int LedDeviceTinkerforge::write(const std::vector &ledValues) return transferLedData(_ledStrip, 0, _colorChannelSize, _redChannel.data(), _greenChannel.data(), _blueChannel.data()); } -int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel) +int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel) { if (length == 0 || index >= length || length > MAX_NUM_LEDS) { diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 5ab89afc..b15153f1 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -90,14 +90,13 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje Info(_log, "Hyperion initialized"); - connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); + //connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); for app restart refactor required + // listen for setting changes connect(_hyperion, &Hyperion::settingsChanged, this, &HyperionDaemon::settingsChanged); // listen for setting changes of framegrabber and v4l2 connect(this, &HyperionDaemon::settingsChanged, this, &HyperionDaemon::handleSettingsUpdate); - // forward system and v4l images to Hyperion - connect(this, &HyperionDaemon::systemImage, _hyperion, &Hyperion::systemImage); - connect(this, &HyperionDaemon::v4lImage, _hyperion, &Hyperion::v4lImage); + // forward videoModes from Hyperion to Daemon evaluation connect(_hyperion, &Hyperion::videoMode, this, &HyperionDaemon::setVideoMode); // forward videoMode changes from Daemon to Hyperion @@ -107,6 +106,7 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) && !defined(ENABLE_X11) && !defined(ENABLE_AMLOGIC) Warning(_log, "No platform capture can be instantiated, because all grabbers have been left out from the build"); #endif + // init system capture (framegrabber) handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE)); // init v4l2 capture @@ -379,7 +379,6 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso Debug(_log, "V4L2 grabber created"); // connect to HyperionDaemon signal - connect(grabber, &V4L2Wrapper::systemImage, this, &HyperionDaemon::v4lImage); connect(this, &HyperionDaemon::videoMode, grabber, &V4L2Wrapper::setVideoMode); connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate); @@ -399,7 +398,6 @@ void HyperionDaemon::createGrabberDispmanx() // connect to HyperionDaemon signal connect(this, &HyperionDaemon::videoMode, _dispmanx, &DispmanxWrapper::setVideoMode); - connect(_dispmanx, &DispmanxWrapper::systemImage, this, &HyperionDaemon::systemImage); connect(this, &HyperionDaemon::settingsChanged, _dispmanx, &DispmanxWrapper::handleSettingsUpdate); _dispmanx->start(); @@ -419,7 +417,6 @@ void HyperionDaemon::createGrabberAmlogic() // connect to HyperionDaemon signal connect(this, &HyperionDaemon::videoMode, _amlGrabber, &AmlogicWrapper::setVideoMode); - connect(_amlGrabber, &AmlogicWrapper::systemImage, this, &HyperionDaemon::systemImage); connect(this, &HyperionDaemon::settingsChanged, _amlGrabber, &AmlogicWrapper::handleSettingsUpdate); _amlGrabber->start(); @@ -440,7 +437,6 @@ void HyperionDaemon::createGrabberX11(const QJsonObject & grabberConfig) // connect to HyperionDaemon signal connect(this, &HyperionDaemon::videoMode, _x11Grabber, &X11Wrapper::setVideoMode); - connect(_x11Grabber, &X11Wrapper::systemImage, this, &HyperionDaemon::systemImage); connect(this, &HyperionDaemon::settingsChanged, _x11Grabber, &X11Wrapper::handleSettingsUpdate); _x11Grabber->start(); @@ -461,7 +457,6 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject & grabberConfig) _fbGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); // connect to HyperionDaemon signal connect(this, &HyperionDaemon::videoMode, _fbGrabber, &FramebufferWrapper::setVideoMode); - connect(_fbGrabber, &FramebufferWrapper::systemImage, this, &HyperionDaemon::systemImage); connect(this, &HyperionDaemon::settingsChanged, _fbGrabber, &FramebufferWrapper::handleSettingsUpdate); _fbGrabber->start(); @@ -482,7 +477,6 @@ void HyperionDaemon::createGrabberOsx(const QJsonObject & grabberConfig) // connect to HyperionDaemon signal connect(this, &HyperionDaemon::videoMode, _osxGrabber, &OsxWrapper::setVideoMode); - connect(_osxGrabber, &OsxWrapper::systemImage, this, &HyperionDaemon::systemImage); connect(this, &HyperionDaemon::settingsChanged, _osxGrabber, &OsxWrapper::handleSettingsUpdate); _osxGrabber->start(); diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index e20bb775..bf6c5b68 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -97,16 +97,6 @@ signals: /// void settingsChanged(const settings::type& type, const QJsonDocument& data); - /// - /// @brief PIPE SystemCapture images from SystemCapture over HyperionDaemon to Hyperion class - /// - void systemImage(const Image& image); - - /// - /// @brief PIPE v4lCapture images from v4lCapture over HyperionDaemon to Hyperion class - /// - void v4lImage(const Image & image); - /// /// @brief After eval of setVideoMode this signal emits with a new one on change ///