diff --git a/protocol/esta/dmx/universe.cpp b/protocol/esta/dmx/universe.cpp index 0393405..3ddf987 100644 --- a/protocol/esta/dmx/universe.cpp +++ b/protocol/esta/dmx/universe.cpp @@ -182,52 +182,38 @@ void Universe::setValue(const uint16_t address, const uint8_t value) void Universe::setData(const std::vector& data) { if (data.empty()) - return; // no data - - if (data.front() != E111_NULL_START) - return setAltData(data); // Alternate Start Code - - // accept variable lenth input, but never more than the limit - const auto max_length = null_start_data.size(); - const auto length = data.size() < max_length ? data.size() : max_length; - { - std::unique_lock lk_data(mtx_data); - if (length < max_length) - null_start_data.fill(0); // wipe old data - std::copy_n(data.cbegin(), length, null_start_data.begin()); // copy new data + return; // no data + switch (data.front()) { + case E111_NULL_START: + rx_dimmer_data_(data); + break; + default: + if (rx_handlers_.count(data.front())) + if (auto sp = rx_handlers_.at(data.front()).lock()) + (*sp)(data); // the owner is still holding the token } - { - std::unique_lock lk_ctl(mtx_control); - active_data_slots_ = length; - } - rx_timeout_(true); // update rx times - do_callbacks_(cb_dataChange); // run callbacks } /** - * @brief Universe::setAltData - * @param data - * - * The base class implimentation is to discard the data. - * - * \attention re-impliment this method to rx custom alternate start code data. + * @brief Universe::onRxData + * @param code + * @param cb + * @return */ -void Universe::setAltData(const std::vector & data) +std::shared_ptr Universe::onRxData(uint8_t code, + const std::function&)> cb) { - switch (data.front()) - { - case E111_ASC_TEXT_ASCII: - break; - case E111_ASC_TEST: - break; - case E111_ASC_TEXT_UTF8: - break; - case E111_ASC_MANUFACTURER: - break; - case E111_ASC_SIP: - break; - } + std::unique_lock lk_ctl(mtx_control); + // wrap the callback with a shared pointer + auto sp = std::make_shared&)>>(std::move(cb)); + // add callback to list (as a weak pointer) + if (rx_handlers_.count(code)) + rx_handlers_[code] = sp; + else + rx_handlers_.insert({code, sp}); + // return token that caller must keep throughout it's scope + return sp; } @@ -265,6 +251,30 @@ std::shared_ptr Universe::onStatusChange(const std::function &data) +{ + // accept variable lenth input, but never more than the limit + const auto max_length = null_start_data.size(); + const auto length = data.size() < max_length ? data.size() : max_length; + { + std::unique_lock lk_data(mtx_data); + if (length < max_length) + null_start_data.fill(0); // wipe old data + std::copy_n(data.cbegin(), length, null_start_data.begin()); // copy new data + } + { + std::unique_lock lk_ctl(mtx_control); + active_data_slots_ = length; + } + rx_timeout_(true); // update rx times + do_callbacks_(cb_dataChange); // run callbacks +} + + /** * @brief Universe::rx_timeout_ * @param add_now diff --git a/protocol/esta/dmx/universe.h b/protocol/esta/dmx/universe.h index 7643906..b94f583 100644 --- a/protocol/esta/dmx/universe.h +++ b/protocol/esta/dmx/universe.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -58,8 +59,8 @@ class Universe { const uint8_t* const data); virtual void setValue(const uint16_t address, const uint8_t value); virtual void setData(const std::vector &); - virtual void setAltData(const std::vector &); + std::shared_ptr onRxData(uint8_t, const std::function&)>); std::shared_ptr onDataChange(const std::function); std::shared_ptr onStatusChange(const std::function); @@ -86,10 +87,12 @@ class Universe { std::chrono::system_clock::time_point last_updated_; //!< time of the latest update private: + void rx_dimmer_data_(const std::vector &); void rx_timeout_(bool add_now = false); const int rx_timeout_period_; uint8_t status_; //!< the operating state of the universe + std::map&)>>> rx_handlers_; std::queue> rx_times_; std::vector>> cb_dataChange; std::vector>> cb_statusChange;