1
0
Fork 0

poly-source universe API cleanup

This commit is contained in:
Kevin Matz 2021-09-10 12:00:50 -04:00
parent dfeff5c344
commit 69bca798c4
10 changed files with 218 additions and 54 deletions

View File

@ -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

View File

@ -24,6 +24,7 @@ public:
void removeChild(MultiverseItem* child);
void removeChildren();
void setOverrideData(QVariant data);
void createChildren();
MultiverseItem * child(int row);
int childCount() const;

View File

@ -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();
});
}

View File

@ -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();
}

View File

@ -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*)

View File

@ -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

View File

@ -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

View File

@ -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
/// >

View File

@ -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

View File

@ -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;