poly-source universe API cleanup
This commit is contained in:
parent
dfeff5c344
commit
69bca798c4
|
@ -19,6 +19,8 @@ MultiverseItem::MultiverseItem(MultiverseItem* parent,
|
|||
, parentItem_(parent)
|
||||
, override_data_(QVariant())
|
||||
{
|
||||
createChildren();
|
||||
|
||||
if(parent)
|
||||
parent->appendChild(this);
|
||||
}
|
||||
|
@ -29,8 +31,7 @@ MultiverseItem::MultiverseItem(MultiverseItem* parent,
|
|||
*/
|
||||
MultiverseItem::~MultiverseItem()
|
||||
{
|
||||
for (const auto & child : childItems_)
|
||||
delete child;
|
||||
qDeleteAll(childItems_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +61,7 @@ void MultiverseItem::removeChild(MultiverseItem* child)
|
|||
*/
|
||||
void MultiverseItem::removeChildren()
|
||||
{
|
||||
qDeleteAll(childItems_);
|
||||
childItems_.clear();
|
||||
}
|
||||
|
||||
|
@ -74,6 +76,24 @@ void MultiverseItem::setOverrideData(QVariant data)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MultiverseItem::createChildren
|
||||
*/
|
||||
void MultiverseItem::createChildren()
|
||||
{
|
||||
if (!universe_)
|
||||
return;
|
||||
|
||||
auto sources = universe_->sources();
|
||||
for (const auto & metadata : sources)
|
||||
{
|
||||
auto universe = universe_->sourceUniverse(metadata);
|
||||
if (universe)
|
||||
new MultiverseItem(this, universe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MultiverseItem::child
|
||||
* @param row
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
void removeChild(MultiverseItem* child);
|
||||
void removeChildren();
|
||||
void setOverrideData(QVariant data);
|
||||
void createChildren();
|
||||
|
||||
MultiverseItem * child(int row);
|
||||
int childCount() const;
|
||||
|
|
|
@ -227,6 +227,17 @@ void MultiverseModel::insert(const QModelIndex &parent,
|
|||
auto end = begin.siblingAtColumn(columnCount() - 1);
|
||||
emit dataChanged(begin, end);
|
||||
});
|
||||
|
||||
connect(universe, &QSacnUniverse::sourceListChanged,
|
||||
this, [=]() {
|
||||
beginRemoveRows(index, 0, child->childCount() - 1);
|
||||
child->removeChildren();
|
||||
endRemoveRows();
|
||||
|
||||
beginInsertRows(index, 0, universe->sources().size() - 1);
|
||||
child->createChildren();
|
||||
endInsertRows();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ QSacnUniverse::QSacnUniverse(QObject *parent, std::shared_ptr<sACN::Universe> un
|
|||
universe_->onData([this](DMX::Universe*) {
|
||||
emit changed();
|
||||
});
|
||||
|
||||
if (!universe->isEditable())
|
||||
universe_->onSourceListChange([this]() {
|
||||
syncSources();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
@ -23,6 +28,12 @@ QSacnUniverse::QSacnUniverse(QObject *parent, std::shared_ptr<sACN::Universe> un
|
|||
*/
|
||||
QSacnUniverse::~QSacnUniverse()
|
||||
{
|
||||
// delete QSacnUniverse sources
|
||||
auto i = sources_.constBegin();
|
||||
while (i != sources_.constEnd()) {
|
||||
delete i.value();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,6 +107,42 @@ bool QSacnUniverse::isEditable() const
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief QSacnUniverse::sources
|
||||
* @return
|
||||
*/
|
||||
QList<sACN::DATA::data_header> QSacnUniverse::sources() const
|
||||
{
|
||||
QList<sACN::DATA::data_header> ret;
|
||||
|
||||
if (!universe_)
|
||||
return ret;
|
||||
|
||||
for (const auto & src : universe_->sources())
|
||||
ret.append(src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief QSacnUniverse::sourceUniverse
|
||||
* @param metadata
|
||||
* @return
|
||||
*/
|
||||
QSacnUniverse* QSacnUniverse::sourceUniverse(
|
||||
const sACN::DATA::data_header& metadata)
|
||||
{
|
||||
if (!universe_)
|
||||
return nullptr;
|
||||
|
||||
if (!sources_.count(metadata))
|
||||
return nullptr;
|
||||
|
||||
return sources_.value(metadata);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief QSacnUniverse::activeSlots
|
||||
* @return
|
||||
|
@ -192,3 +239,38 @@ void QSacnUniverse::setValue (const uint16_t addr, const uint16_t size,
|
|||
universe_->sACN::Universe::setValue(addr, size, profile);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief QSacnUniverse::syncSources
|
||||
*/
|
||||
void QSacnUniverse::syncSources()
|
||||
{
|
||||
QMap<sACN::DATA::data_header, QSacnUniverse*> newSources;
|
||||
|
||||
auto headers = universe_->sources();
|
||||
for (const auto & metadata : headers)
|
||||
{
|
||||
auto it = sources_.find(metadata);
|
||||
if (it == sources_.end())
|
||||
{ // not found
|
||||
auto universe = universe_->sourceUniverse(metadata);
|
||||
newSources.insert(metadata, new QSacnUniverse(this, universe));
|
||||
}
|
||||
else
|
||||
{ // found
|
||||
auto universe = sources_.take(metadata);
|
||||
newSources.insert(metadata, universe);
|
||||
}
|
||||
}
|
||||
|
||||
// delete any QSacnUniverse that are no longer sources
|
||||
auto i = sources_.constBegin();
|
||||
while (i != sources_.constEnd()) {
|
||||
delete i.value();
|
||||
++i;
|
||||
}
|
||||
|
||||
sources_ = newSources;
|
||||
emit sourceListChanged();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
|
||||
#include "qsacn_global.h"
|
||||
#include "sacn/universe.h"
|
||||
|
@ -24,6 +26,8 @@ public:
|
|||
uint8_t slot(const u_int16_t) const;
|
||||
uint16_t activeSlots() const;
|
||||
bool isEditable() const;
|
||||
QList<sACN::DATA::data_header> sources() const;
|
||||
QSacnUniverse* sourceUniverse(const sACN::DATA::data_header&);
|
||||
|
||||
public slots:
|
||||
void setDescription(std::string desc);
|
||||
|
@ -37,8 +41,10 @@ public slots:
|
|||
|
||||
signals:
|
||||
void changed();
|
||||
void sourceListChanged();
|
||||
|
||||
private:
|
||||
std::shared_ptr<sACN::Universe> universe_;
|
||||
QMap<sACN::DATA::data_header, QSacnUniverse*> sources_;
|
||||
};
|
||||
Q_DECLARE_METATYPE(QSacnUniverse*)
|
||||
|
|
|
@ -44,10 +44,6 @@ ArbitratingUniverse::~ArbitratingUniverse()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MergeProxyUniverse::sources
|
||||
* @return
|
||||
*/
|
||||
const std::vector<DATA::data_header> ArbitratingUniverse::sources() const
|
||||
{
|
||||
std::vector<DATA::data_header> keys;
|
||||
|
@ -65,7 +61,8 @@ const std::vector<DATA::data_header> ArbitratingUniverse::sources() const
|
|||
std::shared_ptr<Universe> ArbitratingUniverse::sourceUniverse(const DATA::data_header &src)
|
||||
{
|
||||
if (!hasSourceUniverse(src))
|
||||
newProvenance_(src);
|
||||
return nullptr;
|
||||
|
||||
return sources_.at(src);
|
||||
}
|
||||
|
||||
|
@ -81,15 +78,15 @@ bool ArbitratingUniverse::hasSourceUniverse(const DATA::data_header& src) const
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MergeProxyUniverse::hassources
|
||||
* @return
|
||||
*/
|
||||
bool ArbitratingUniverse::hasSources() const
|
||||
std::shared_ptr<Universe> ArbitratingUniverse::addNewSource(const DATA::data_header &src)
|
||||
{
|
||||
if (sources_.size())
|
||||
return true;
|
||||
return false;
|
||||
sources_.emplace(src, std::make_shared<Universe>());
|
||||
sources_.at(src)->onData(std::bind(&sACN::ArbitratingUniverse::dataChangedNotifier,
|
||||
this, std::placeholders::_1));
|
||||
for (const auto & cb : cb_sourceListChange)
|
||||
cb();
|
||||
|
||||
return sources_.at(src);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,21 +96,12 @@ bool ArbitratingUniverse::hasSources() const
|
|||
*/
|
||||
void ArbitratingUniverse::deleteSourceUniverse(const DATA::data_header& src)
|
||||
{
|
||||
if (sources_.count(src))
|
||||
{
|
||||
delete sources_.at(src);
|
||||
sources_.erase(src);
|
||||
}
|
||||
}
|
||||
if (!hasSourceUniverse(src))
|
||||
return;
|
||||
|
||||
|
||||
/**
|
||||
* @brief MergeProxyUniverse::addSourceUniverse
|
||||
* @param universe
|
||||
*/
|
||||
void ArbitratingUniverse::addSourceUniverse(Universe* universe)
|
||||
{
|
||||
sources_.at(*universe->provenance()) = universe;
|
||||
sources_.erase(src);
|
||||
for (const auto & cb : cb_sourceListChange)
|
||||
cb();
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,6 +121,16 @@ void ArbitratingUniverse::dataChangedNotifier(DMX::Universe* dmx)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief ArbitratingUniverse::onSourceListChange
|
||||
* @param cb
|
||||
*/
|
||||
void ArbitratingUniverse::onSourceListChange(std::function<void()> cb)
|
||||
{
|
||||
cb_sourceListChange.push_back(cb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MergeProxyUniverse::isSyncronized
|
||||
* @return
|
||||
|
@ -172,11 +170,12 @@ std::shared_ptr<DATA::data_header> ArbitratingUniverse::provenance() const
|
|||
void ArbitratingUniverse::set(std::shared_ptr<ACN::DMP::Pdu> pdu,
|
||||
std::shared_ptr<DATA::data_header> src)
|
||||
{
|
||||
if (expectedUniverse != 0 && src->universe != expectedUniverse)
|
||||
if (expectedUniverse != 0 &&
|
||||
src->universe != expectedUniverse)
|
||||
return;
|
||||
|
||||
if (!sources_.count(*src))
|
||||
newProvenance_(*src);
|
||||
addNewSource(*src);
|
||||
|
||||
sources_.at(*src)->set(pdu, src);
|
||||
}
|
||||
|
@ -238,9 +237,9 @@ double ArbitratingUniverse::rxRate()
|
|||
* @brief MergeProxyUniverse::dominant_
|
||||
* @return
|
||||
*/
|
||||
Universe* ArbitratingUniverse::dominant_() const
|
||||
std::shared_ptr<Universe> ArbitratingUniverse::dominant_() const
|
||||
{
|
||||
Universe* ret = nullptr;
|
||||
std::shared_ptr<Universe> ret = nullptr;
|
||||
for (auto& [_, uni] : sources_)
|
||||
{
|
||||
if (uni->rxRate() < (DMX::E111_DATA_LOSS_TIMEOUT / 1000.0))
|
||||
|
@ -251,16 +250,4 @@ Universe* ArbitratingUniverse::dominant_() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief MergeProxyUniverse::newSource_
|
||||
* @param src
|
||||
*/
|
||||
void ArbitratingUniverse::newProvenance_(const DATA::data_header &src)
|
||||
{
|
||||
sources_.emplace(src, new Universe());
|
||||
sources_.at(src)->onData(std::bind(&sACN::ArbitratingUniverse::dataChangedNotifier,
|
||||
this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
} // namespace SACN
|
||||
|
|
|
@ -62,32 +62,38 @@ public:
|
|||
uint16_t expectedUniverse; ///< Expected universe number
|
||||
|
||||
// Source universes:
|
||||
const std::vector<DATA::data_header> sources() const;
|
||||
Universe* sourceUniverse(const DATA::data_header&);
|
||||
bool hasSourceUniverse(const DATA::data_header&) const;
|
||||
bool hasSources() const;
|
||||
void deleteSourceUniverse(const DATA::data_header&);
|
||||
void addSourceUniverse(Universe *);
|
||||
void dataChangedNotifier(DMX::Universe* universe);
|
||||
|
||||
// SACN::Universe overrides:
|
||||
void set(std::shared_ptr<ACN::DMP::Pdu>, std::shared_ptr<DATA::data_header>) override;
|
||||
|
||||
std::shared_ptr<DATA::data_header> provenance() const override;
|
||||
void setProvenance(std::shared_ptr<DATA::data_header>) override {};
|
||||
|
||||
bool isSyncronized() const override;
|
||||
void synchronize(uint8_t = 0) override;
|
||||
|
||||
bool isEditable() const override;
|
||||
|
||||
uint16_t activeSlots() const override;
|
||||
|
||||
// api for poly-source universes
|
||||
const std::vector<DATA::data_header> sources() const override;
|
||||
std::shared_ptr<Universe> sourceUniverse(const DATA::data_header&) override;
|
||||
std::shared_ptr<Universe> addNewSource(const DATA::data_header&) override;
|
||||
void onSourceListChange(std::function<void()>) override;
|
||||
|
||||
// DMX::Universe Overrides:
|
||||
uint8_t slot(const uint16_t) const override;
|
||||
double rxRate() override;
|
||||
|
||||
private:
|
||||
std::unordered_map<DATA::data_header, std::shared_ptr<Universe>> sources_;
|
||||
std::vector<std::function<void()>> cb_sourceListChange; //!< list of calback functions
|
||||
|
||||
std::shared_ptr<Universe> dominant_() const;
|
||||
void newProvenance_(const DATA::data_header&);
|
||||
bool hasSourceUniverse(const DATA::data_header&) const;
|
||||
};
|
||||
|
||||
} // SACN namespace
|
||||
|
|
|
@ -200,6 +200,8 @@ void Receiver::dataFrameHandler(ACN::PDU::Message<DATA::Pdu> frame) {
|
|||
if (!universes_.count(source->universe))
|
||||
return;
|
||||
auto universe = universes_.at(source->universe)->sourceUniverse(*source);
|
||||
if (!universe)
|
||||
universe = universes_.at(source->universe)->addNewSource(*source);
|
||||
|
||||
/// > \cite sACN 6.2.6 E1.31 Data Packet: Options
|
||||
/// >
|
||||
|
|
|
@ -175,6 +175,50 @@ bool Universe::isEditable() const
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Universe::sources
|
||||
* @return
|
||||
*/
|
||||
const std::vector<DATA::data_header> Universe::sources() const
|
||||
{
|
||||
std::vector<DATA::data_header> keys;
|
||||
keys.push_back(*provenance_);
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a callback to be notified when the source list changes.
|
||||
*/
|
||||
void Universe::onSourceListChange(std::function<void()>)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief sourceUniverse
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<Universe> Universe::sourceUniverse(const DATA::data_header& src)
|
||||
{
|
||||
if (src == *provenance())
|
||||
return shared_from_this();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Universe::addNewSource
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<Universe> Universe::addNewSource(const DATA::data_header&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Universe::activeSlots
|
||||
* @return
|
||||
|
|
|
@ -45,6 +45,7 @@ class Source; ///< forward declare from "sacn/source.h"
|
|||
*/
|
||||
class Universe
|
||||
: public DMX::Universe
|
||||
, public std::enable_shared_from_this<Universe>
|
||||
{
|
||||
public:
|
||||
Universe(Source* = nullptr);
|
||||
|
@ -59,13 +60,19 @@ public:
|
|||
virtual void synchronize(uint8_t = 0);
|
||||
|
||||
virtual bool isEditable() const;
|
||||
|
||||
virtual uint16_t activeSlots() const;
|
||||
|
||||
// api for poly-source universes
|
||||
virtual const std::vector<DATA::data_header> sources() const;
|
||||
virtual std::shared_ptr<Universe> sourceUniverse(const DATA::data_header&);
|
||||
virtual std::shared_ptr<Universe> addNewSource(const DATA::data_header&);
|
||||
virtual void onSourceListChange(std::function<void()>);
|
||||
|
||||
// DMX::Universe overrides
|
||||
void setValue (const uint16_t address, const uint8_t value) override;
|
||||
void setValue (const uint16_t start, const uint16_t footprint,
|
||||
const uint8_t* data) override;
|
||||
|
||||
/**
|
||||
* @brief destination IP address
|
||||
*
|
||||
|
@ -73,8 +80,6 @@ public:
|
|||
*/
|
||||
ipAddress destination;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void sACNsend() const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue