diff --git a/protocol/esta/sacn/universe.cpp b/protocol/esta/sacn/universe.cpp index 6afc062..a13599c 100644 --- a/protocol/esta/sacn/universe.cpp +++ b/protocol/esta/sacn/universe.cpp @@ -22,7 +22,6 @@ SOFTWARE. */ -#include "source.h" #include "universe.h" namespace sACN { @@ -35,7 +34,6 @@ Universe::Universe(Source* src) : DMX::Universe(E131_NETWORK_DATA_LOSS_TIMEOUT) , ACN::DMP::Component(UUID::uuid(), "OpenLCP sACN Universe") , metadata_(std::make_shared()) - , source_(src) , active_data_slots_(1) // start code , sync_sequence_(0) , sender_(nullptr) @@ -44,10 +42,7 @@ Universe::Universe(Source* src) // create a sending thread if (src) - sender_ = new UniverseSender(this); - - // add ourself as a sender of our own DMP messages - addDmpSender(std::bind(&Universe::dataFrameSender, this, std::placeholders::_1)); + sender_ = new UniverseSender(src, this); } @@ -162,7 +157,7 @@ bool Universe::isSyncronized() */ bool Universe::isEditable() const { - return source_; + return sender_; } @@ -324,71 +319,4 @@ void Universe::setSyncData(const std::vector & data) sync_data_ = new std::vector(data); } - -/** - * @brief Universe::as_DMP_ - * @return - */ -ACN::PDU::Message Universe::as_DMP_() const -{ - // header - auto addrtyp = std::make_shared(); - addrtyp->address_length = ACN::DMP::TWO; - addrtyp->x_reserved = 0; - addrtyp->data_type = ACN::DMP::ARRAY; - addrtyp->relative = false; - addrtyp->z_reserved = true; // buy why? Its in the standard... - - // property range - ACN::DMP::Range pr(*addrtyp); - pr.address = 0; - pr.incriment = 1; - pr.count = active_data_slots_ < null_start_data.size() ? active_data_slots_ : null_start_data.size(); - - // property data - std::vector pd; - std::copy_n(null_start_data.begin(), pr.count, std::back_inserter(pd)); - - // data segment - auto addrlst = std::make_shared(*addrtyp); - addrlst->properties.emplace_back(ACN::DMP::address_data_pair(pr, pd)); - - // DMP layer - auto dmp = std::make_shared(); - dmp->setVector(ACN::DMP::SET_PROPERTY); - dmp->setHeader(addrtyp); - dmp->setData(addrlst); - - return dmp; -} - - - -/** - * @brief Universe::dataFrameSender - * @param dmp - */ -void Universe::dataFrameSender(ACN::PDU::Message dmp) const -{ - // sACN Framing Layer - auto frame = std::make_shared(); - frame->setVector(VECTOR_E131_DATA_PACKET); - frame->setHeader(metadata_); - frame->setData(dmp); - - // send - switch (destination.type) - { - case ACN::SDT::SDT_ADDR_NULL: - source_->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, - IPv4MulticastAddress(metadata_->universe)); - source_->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, - IPv6MulticastAddress(metadata_->universe)); - break; - default: - source_->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, destination); - } -} - - }; // namespace SACN diff --git a/protocol/esta/sacn/universe.h b/protocol/esta/sacn/universe.h index 75e0760..a7becef 100644 --- a/protocol/esta/sacn/universe.h +++ b/protocol/esta/sacn/universe.h @@ -34,8 +34,6 @@ namespace sACN { -class Source; ///< forward declare from "sacn/source.h" - /** * @brief \cite sACN 3.2 Universe * @@ -95,8 +93,6 @@ public: }; protected: - void dataFrameSender(ACN::PDU::Message) const; - // ACN::DMP::Component overrides virtual void rxDmpGetProperty(ACN::PDU::Message) override; virtual void rxDmpSetProperty(ACN::PDU::Message) override; @@ -105,7 +101,6 @@ protected: private: std::shared_ptr metadata_; std::vector * sync_data_ = nullptr; - Source* source_; /** * @brief \cite sACN 3.7 Active Data Slots @@ -132,7 +127,6 @@ private: uint8_t sync_sequence_; UniverseSender * sender_; - ACN::PDU::Message as_DMP_() const; }; } // SACN namespace diff --git a/protocol/esta/sacn/universesender.cpp b/protocol/esta/sacn/universesender.cpp index fa3620a..bae4ef9 100644 --- a/protocol/esta/sacn/universesender.cpp +++ b/protocol/esta/sacn/universesender.cpp @@ -23,23 +23,45 @@ */ #include "universesender.h" #include "universe.h" +#include "source.h" namespace sACN { /** * @brief UniverseSender::UniverseSender + * @param source * @param universe */ -UniverseSender::UniverseSender(Universe * universe) - : mUniverse(universe) +UniverseSender::UniverseSender(Source * source, Universe * universe) + : mSource(source) + , mUniverse(universe) , terminated_resend(3) , minimum_update_time(22700) , last_null_data({0}) , retransmission_count(0) , keep_alive_interval(800) , enable_(true) - , worker_(&UniverseSender::loop_, this) + , dmp_(std::make_shared()) { + // add ourself as a sender for DMP messages + mUniverse->addDmpSender(std::bind(&UniverseSender::dataFrameSender, this, + std::placeholders::_1)); + + // header segment + auto addrtyp = std::make_shared(); + addrtyp->address_length = ACN::DMP::TWO; + addrtyp->x_reserved = 0; + addrtyp->data_type = ACN::DMP::ARRAY; + addrtyp->relative = false; + addrtyp->z_reserved = true; // buy why? Its in the standard... + + // DMP layer + dmp_->setVector(ACN::DMP::SET_PROPERTY); + dmp_->setHeader(addrtyp); + update_dmp_(); // initial data segment + + // start the thread after setting up the PDU + worker_ = std::thread(&UniverseSender::loop_, this); } @@ -119,6 +141,7 @@ void UniverseSender::loop_() { last_null_data = mUniverse->null_start_data; retransmission_count = 0; + update_dmp_(); } mUniverse->null_start_mutex.unlock(); if (++retransmission_count > 3) @@ -138,7 +161,7 @@ void UniverseSender::loop_() } // send the sACN message - mUniverse->sendDMP(mUniverse->as_DMP_()); + mUniverse->sendDMP(dmp_); mUniverse->last_updated_ = std::chrono::system_clock::now(); /// > \cite sACN 6.2.5 E1.31 Data Packet: Sequence Number /// > @@ -152,4 +175,57 @@ void UniverseSender::loop_() } +/** + * @brief UniverseSender::update_dmp_ + */ +void UniverseSender::update_dmp_() +{ + // header segment + auto addrtyp = std::static_pointer_cast(dmp_->header()); + + // property range + ACN::DMP::Range pr(*addrtyp); + pr.address = 0; + pr.incriment = 1; + pr.count = mUniverse->active_data_slots_ < mUniverse->null_start_data.size() + ? mUniverse->active_data_slots_ + : mUniverse->null_start_data.size(); + + // property data + std::vector pd; + std::copy_n(mUniverse->null_start_data.begin(), pr.count, std::back_inserter(pd)); + + // data segment + auto addrlst = std::make_shared(*addrtyp); + addrlst->properties.emplace_back(ACN::DMP::address_data_pair(pr, pd)); + dmp_->setData(addrlst); +} + + +/** + * @brief Universe::dataFrameSender + * @param dmp + */ +void UniverseSender::dataFrameSender(ACN::PDU::Message dmp) const +{ + // sACN Framing Layer + auto frame = std::make_shared(); + frame->setVector(VECTOR_E131_DATA_PACKET); + frame->setHeader(mUniverse->metadata_); + frame->setData(dmp); + + // send + switch (mUniverse->destination.type) + { + case ACN::SDT::SDT_ADDR_NULL: + mSource->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, + IPv4MulticastAddress(mUniverse->metadata_->universe)); + mSource->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, + IPv6MulticastAddress(mUniverse->metadata_->universe)); + break; + default: + mSource->rlpSendUdp(VECTOR_ROOT_E131_DATA, frame, mUniverse->destination); + } +} + } // namespace sACN diff --git a/protocol/esta/sacn/universesender.h b/protocol/esta/sacn/universesender.h index ea24aaa..8602b34 100644 --- a/protocol/esta/sacn/universesender.h +++ b/protocol/esta/sacn/universesender.h @@ -24,6 +24,7 @@ #pragma once #include "../dmx/universe.h" +#include "dmp.h" #include #include #include @@ -31,6 +32,7 @@ namespace sACN { class Universe; +class Source; /** * @brief The UniverseSender class @@ -38,7 +40,7 @@ class Universe; class UniverseSender { public: - UniverseSender(Universe *); + UniverseSender(Source*, Universe *); ~UniverseSender(); bool isSending(); @@ -47,6 +49,7 @@ public: void kill(); private: + Source * mSource; Universe * mUniverse; /// \cite sACN 6.2.6 E1.31 Data Packet: Options - Stream_Terminated @@ -83,6 +86,10 @@ private: std::condition_variable_any request_; std::thread worker_; void loop_(); + + void update_dmp_(); + ACN::PDU::Message dmp_; + void dataFrameSender(ACN::PDU::Message) const; }; } // namespace sACN