diff --git a/protocol/dmx/universe.cpp b/protocol/dmx/universe.cpp index bd005fc..3e18947 100644 --- a/protocol/dmx/universe.cpp +++ b/protocol/dmx/universe.cpp @@ -50,7 +50,7 @@ Universe::~Universe() * @param address * @return */ -uint8_t Universe::slot(const uint16_t address) const +uint8_t Universe::slot(const uint16_t address) { if (address == 0) return 0; diff --git a/protocol/dmx/universe.h b/protocol/dmx/universe.h index 0cc540c..339bf29 100644 --- a/protocol/dmx/universe.h +++ b/protocol/dmx/universe.h @@ -50,7 +50,7 @@ class Universe { Universe (int timeout_period = E111_DATA_LOSS_TIMEOUT); virtual ~Universe (); - virtual uint8_t slot (const uint16_t) const; + virtual uint8_t slot (const uint16_t); virtual double rxRate(); virtual uint rxAge(); diff --git a/protocol/sacn/arbitratinguniverse.cpp b/protocol/sacn/arbitratinguniverse.cpp index 82bad5a..78bcd6e 100644 --- a/protocol/sacn/arbitratinguniverse.cpp +++ b/protocol/sacn/arbitratinguniverse.cpp @@ -135,7 +135,7 @@ void ArbitratingUniverse::onSourceListChange(std::function cb) * @brief MergeProxyUniverse::isSyncronized * @return */ -bool ArbitratingUniverse::isSyncronized() const +bool ArbitratingUniverse::isSyncronized() { auto universe = dominant_(); if (!universe) @@ -148,7 +148,7 @@ bool ArbitratingUniverse::isSyncronized() const * @brief MergeProxyUniverse::provenance * @return */ -std::shared_ptr ArbitratingUniverse::provenance() const +std::shared_ptr ArbitratingUniverse::provenance() { auto universe = dominant_(); if (universe) @@ -197,7 +197,7 @@ bool ArbitratingUniverse::isEditable() const { } -uint16_t ArbitratingUniverse::activeSlots() const +uint16_t ArbitratingUniverse::activeSlots() { auto universe = dominant_(); if (!universe) @@ -211,7 +211,7 @@ uint16_t ArbitratingUniverse::activeSlots() const * @param s * @return */ -uint8_t ArbitratingUniverse::slot(const uint16_t s) const +uint8_t ArbitratingUniverse::slot(const uint16_t s) { auto universe = dominant_(); if (!universe) @@ -237,16 +237,47 @@ double ArbitratingUniverse::rxRate() * @brief MergeProxyUniverse::dominant_ * @return */ -std::shared_ptr ArbitratingUniverse::dominant_() const +std::shared_ptr ArbitratingUniverse::dominant_() { + bool sourceListChanged = false; std::shared_ptr ret = nullptr; - for (auto& [_, uni] : sources_) + + for(auto it = sources_.begin(); it != sources_.end(); ) { - if (uni->rxRate() < (DMX::E111_DATA_LOSS_TIMEOUT / 1000.0)) - continue; // stale universes cannot be dominant - if (!ret || uni->provenance() > ret->provenance()) - ret = uni; + auto universe = it->second; + + if (!ret) + { // anything is better than nothing! + ++it; + ret = universe; + continue; + } + + auto age = universe->rxAge(); + + if (age > E131_NETWORK_DATA_LOSS_TIMEOUT) + { // clean up zombie universes + it = sources_.erase(it); + sourceListChanged = true; + continue; + } + + if (age > DMX::E111_DATA_LOSS_TIMEOUT) + { + ++it; + continue; // stale universes cannot be dominant + } + + if (!ret || universe->provenance() > ret->provenance()) + ret = universe; // rank by provenance + + ++it; } + + if (sourceListChanged) + for (const auto & cb : cb_sourceListChange) + cb(); + return ret; } diff --git a/protocol/sacn/arbitratinguniverse.h b/protocol/sacn/arbitratinguniverse.h index 96fbb5e..97c4d3e 100644 --- a/protocol/sacn/arbitratinguniverse.h +++ b/protocol/sacn/arbitratinguniverse.h @@ -68,15 +68,15 @@ public: // SACN::Universe overrides: void set(std::shared_ptr, std::shared_ptr) override; - std::shared_ptr provenance() const override; + std::shared_ptr provenance() override; void setProvenance(std::shared_ptr) override {}; - bool isSyncronized() const override; + bool isSyncronized() override; void synchronize(uint8_t = 0) override; bool isEditable() const override; - uint16_t activeSlots() const override; + uint16_t activeSlots() override; // api for poly-source universes const std::vector sources() const override; @@ -85,14 +85,14 @@ public: void onSourceListChange(std::function) override; // DMX::Universe Overrides: - uint8_t slot(const uint16_t) const override; + uint8_t slot(const uint16_t) override; double rxRate() override; private: std::unordered_map> sources_; std::vector> cb_sourceListChange; //!< list of calback functions - std::shared_ptr dominant_() const; + std::shared_ptr dominant_(); bool hasSourceUniverse(const DATA::data_header&) const; }; diff --git a/protocol/sacn/universe.cpp b/protocol/sacn/universe.cpp index 4e045f4..5332515 100644 --- a/protocol/sacn/universe.cpp +++ b/protocol/sacn/universe.cpp @@ -159,7 +159,7 @@ void Universe::setProvenance(std::shared_ptr source) * @brief Universe::isSyncronized * @return */ -bool Universe::isSyncronized() const +bool Universe::isSyncronized() { return (!sync_data_); }; @@ -223,7 +223,7 @@ std::shared_ptr Universe::addNewSource(const DATA::data_header&) * @brief Universe::activeSlots * @return */ -uint16_t Universe::activeSlots() const +uint16_t Universe::activeSlots() { return active_data_slots; } @@ -291,7 +291,7 @@ void Universe::setValue (const uint16_t start, const uint16_t footprint, * @brief Universe::source * @return */ -std::shared_ptr Universe::provenance() const +std::shared_ptr Universe::provenance() { return provenance_; } diff --git a/protocol/sacn/universe.h b/protocol/sacn/universe.h index bcf2364..b4c2aa9 100644 --- a/protocol/sacn/universe.h +++ b/protocol/sacn/universe.h @@ -53,15 +53,15 @@ public: virtual void set(ACN::PDU::Message, std::shared_ptr); - virtual std::shared_ptr provenance() const; + virtual std::shared_ptr provenance(); virtual void setProvenance(std::shared_ptr); - virtual bool isSyncronized() const; + virtual bool isSyncronized(); virtual void synchronize(uint8_t = 0); virtual bool isEditable() const; - virtual uint16_t activeSlots() const; + virtual uint16_t activeSlots(); // api for poly-source universes virtual const std::vector sources() const;