support discovering available sACN universes
This commit is contained in:
parent
15b611983a
commit
50f29808ef
|
@ -33,6 +33,7 @@ set(SOURCE_FILES
|
|||
dmx/universe.h
|
||||
sacn/data.cpp
|
||||
sacn/data.h
|
||||
sacn/extended.cpp
|
||||
sacn/extended.h
|
||||
sacn/receiver.cpp
|
||||
sacn/receiver.h
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
extended.cpp
|
||||
|
||||
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "extended.h"
|
||||
|
||||
namespace SACN {
|
||||
namespace EXTENDED {
|
||||
|
||||
|
||||
frame_sync_header::frame_sync_header(PDU::Stream stream) {
|
||||
sequence_number = stream->read8();
|
||||
sync_address = stream->read16();
|
||||
stream->read(reserved, sizeof(reserved));
|
||||
if (stream->gcount() != sizeof(reserved))
|
||||
stream->setstate(stream->rdstate() | std::ios_base::failbit);
|
||||
}
|
||||
|
||||
|
||||
frame_discovery_header::frame_discovery_header(PDU::Stream stream) {
|
||||
stream->read(source_name, sizeof(source_name));
|
||||
if (stream->gcount() != sizeof(source_name))
|
||||
stream->setstate(stream->rdstate() | std::ios_base::failbit);
|
||||
stream->read(reserved, sizeof(reserved));
|
||||
if (stream->gcount() != sizeof(reserved))
|
||||
stream->setstate(stream->rdstate() | std::ios_base::failbit);
|
||||
}
|
||||
|
||||
|
||||
Pdu::Pdu(PDU::Stream stream)
|
||||
: PDU::Pdu(stream, 4) // vectors are 4 octets
|
||||
{
|
||||
if (stream->fail()) return;
|
||||
if (!buffer_->good()) return;
|
||||
|
||||
if (flags_.hasHeader)
|
||||
switch(vector()) {
|
||||
case VECTOR_E131_EXTENDED_SYNCHRONIZATION:
|
||||
setHeader(new frame_sync_header(buffer_));
|
||||
break;
|
||||
case VECTOR_E131_EXTENDED_DISCOVERY:
|
||||
setHeader(new frame_discovery_header(buffer_));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DISCOVERY {
|
||||
|
||||
discovery_list_header::discovery_list_header(PDU::Stream stream) {
|
||||
page = stream->read8();
|
||||
last_page = stream->read8();
|
||||
}
|
||||
|
||||
|
||||
Pdu::Pdu(PDU::Stream stream)
|
||||
: PDU::Pdu(stream, 4) // vectors are 4 octets
|
||||
{
|
||||
if (stream->fail()) return;
|
||||
if (!buffer_->good()) return;
|
||||
|
||||
if (flags_.hasHeader)
|
||||
setHeader(new discovery_list_header(buffer_));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Construct a Universe Source from an sACN discovery layer PDU
|
||||
*/
|
||||
DiscoveredUniverse::DiscoveredUniverse(const std::shared_ptr<EXTENDED::DISCOVERY::Pdu> pdu) {
|
||||
auto root_header = (RLP::rlp_header*)pdu->parent()->parent()->header();
|
||||
cid_ = root_header->cid;
|
||||
|
||||
auto frame_header = (EXTENDED::frame_discovery_header*)pdu->parent()->header();
|
||||
description_ = std::string((char*)frame_header->source_name);
|
||||
|
||||
universe_ = pdu->buffer()->read16();
|
||||
}
|
||||
|
||||
} // DISCOVERY
|
||||
} // EXTENDED
|
||||
} // SACN
|
|
@ -24,6 +24,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "sacn.h"
|
||||
#include <functional>
|
||||
|
||||
namespace SACN {
|
||||
using namespace ACN;
|
||||
|
@ -37,6 +38,7 @@ struct frame_sync_header : PDU::pdu_header {
|
|||
uint8_t sequence_number;
|
||||
uint16_t sync_address;
|
||||
uint8_t reserved[2];
|
||||
frame_sync_header(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,14 +46,56 @@ struct frame_sync_header : PDU::pdu_header {
|
|||
struct frame_discovery_header : PDU::pdu_header {
|
||||
uint8_t source_name[64];
|
||||
uint8_t reserved[4];
|
||||
frame_discovery_header(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
class Pdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
public:
|
||||
Pdu(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
namespace DISCOVERY {
|
||||
|
||||
// Table 8-9: E1.31 Universe Discovery Packet Universe Discovery Layer
|
||||
struct discovery_list_header : PDU::pdu_header {
|
||||
uint8_t page;
|
||||
uint8_t last_page;
|
||||
discovery_list_header(PDU::Stream);
|
||||
};
|
||||
|
||||
class Pdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
public:
|
||||
Pdu(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
universe metadata
|
||||
*/
|
||||
class DiscoveredUniverse
|
||||
{
|
||||
public:
|
||||
DiscoveredUniverse(const std::shared_ptr<EXTENDED::DISCOVERY::Pdu>);
|
||||
|
||||
const UUID::uuid cid() const {return cid_;};
|
||||
const std::string description() const {return description_;}
|
||||
const uint16_t universe() const {return universe_;}
|
||||
|
||||
private:
|
||||
UUID::uuid cid_;
|
||||
std::string description_;
|
||||
uint16_t universe_;
|
||||
};
|
||||
|
||||
using Watcher = std::function<void(std::shared_ptr<DiscoveredUniverse>)>;
|
||||
|
||||
|
||||
} // DISCOVERY
|
||||
} // EXTENDED
|
||||
} // SACN
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
|
||||
#include "receiver.h"
|
||||
#include "data.h"
|
||||
|
||||
namespace SACN {
|
||||
|
||||
|
@ -56,11 +55,29 @@ SACN::Universe * Receiver::universe(uint16_t universe) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Receiver::discoveryStart() {
|
||||
subscribe(SACN::E131_DISCOVERY_UNIVERSE);
|
||||
}
|
||||
|
||||
void Receiver::discoveryStop() {
|
||||
unsubscribe(SACN::E131_DISCOVERY_UNIVERSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
register a discovery consumer callback function
|
||||
|
||||
@param const Watcher something that wants to know about available universes.
|
||||
*/
|
||||
void Receiver::onDiscovered(const EXTENDED::DISCOVERY::Watcher cb) {
|
||||
discoveryCallbacks_.push_back(cb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Receive VECTOR_ROOT_E131_DATA vector'd packets.
|
||||
|
||||
@param pdu is a shared pointer to the PDU
|
||||
@param root is a shared pointer to the PDU
|
||||
*/
|
||||
void Receiver::rootDataHandler(std::shared_ptr<RLP::Pdu> root) {
|
||||
auto block = PDU::readBlock<DATA::Pdu>(root->buffer(), root);
|
||||
|
@ -82,6 +99,70 @@ void Receiver::rootDataHandler(std::shared_ptr<RLP::Pdu> root) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
Receive VECTOR_ROOT_E131_EXTENDED vector'd packets.
|
||||
|
||||
@param root is a shared pointer to the PDU
|
||||
*/
|
||||
void Receiver::rootExtendedHandler(std::shared_ptr<RLP::Pdu> root) {
|
||||
auto block = PDU::readBlock<EXTENDED::Pdu>(root->buffer(), root);
|
||||
if (root->buffer()->fail())
|
||||
return;
|
||||
for(auto const &frame : *block) {
|
||||
switch(frame->vector()) {
|
||||
// 6.3 E1.31 Synchronization Packet Framing Layer
|
||||
case VECTOR_E131_EXTENDED_SYNCHRONIZATION:
|
||||
syncPacketHandler(frame);
|
||||
break;
|
||||
// 6.4 E1.31 Universe Discovery Packet Framing Layer
|
||||
case VECTOR_E131_EXTENDED_DISCOVERY:
|
||||
discoveryPacketHandler(frame);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Receiver::discoveryPacketHandler(std::shared_ptr<EXTENDED::Pdu> frame) {
|
||||
auto block = PDU::readBlock<EXTENDED::DISCOVERY::Pdu>(frame->buffer(), frame);
|
||||
if (frame->buffer()->fail())
|
||||
return;
|
||||
|
||||
for(auto const &pdu : *block) {
|
||||
// 8 Universe Discovery Layer
|
||||
// Universe Discovery data only appears in E1.31 Universe Discovery
|
||||
// Packets and shall not be included in E1.31 Data Packets or E1.31
|
||||
// Synchronization Packets.
|
||||
switch(pdu->vector()) {
|
||||
case VECTOR_UNIVERSE_DISCOVERY_UNIVERSE_LIST:
|
||||
discoveryListHanlder(pdu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Receiver::discoveryListHanlder(std::shared_ptr<EXTENDED::DISCOVERY::Pdu> pdu) {
|
||||
// header may be inherited. check that one exists
|
||||
if (!pdu->header())
|
||||
return;
|
||||
|
||||
while(pdu->buffer()->good()) {
|
||||
auto found = std::shared_ptr<EXTENDED::DISCOVERY::DiscoveredUniverse>
|
||||
(new EXTENDED::DISCOVERY::DiscoveredUniverse(pdu));
|
||||
if (pdu->buffer()->fail()) break;
|
||||
if (!pdu->buffer()->good()) break;
|
||||
|
||||
for (const auto &cb : discoveryCallbacks_)
|
||||
cb(found);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Receive `VECTOR_ROOT_E131_DATA -> VECTOR_E131_DATA_PACKET` vector'd packets.
|
||||
|
||||
|
|
|
@ -24,9 +24,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "data.h"
|
||||
#include "extended.h"
|
||||
#include "sacn.h"
|
||||
#include "universe.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace SACN {
|
||||
|
||||
|
@ -39,16 +41,24 @@ public:
|
|||
virtual void unsubscribe(const uint16_t);
|
||||
SACN::Universe * universe(uint16_t universe);
|
||||
|
||||
void discoveryStart();
|
||||
void discoveryStop();
|
||||
void onDiscovered(const EXTENDED::DISCOVERY::Watcher);
|
||||
|
||||
protected:
|
||||
// process data frames
|
||||
void rootDataHandler(std::shared_ptr<RLP::Pdu>);
|
||||
void dataPacketHandler(std::shared_ptr<DATA::Pdu>);
|
||||
|
||||
// process extended frames
|
||||
void rootExtendedHandler(std::shared_ptr<RLP::Pdu>) {};
|
||||
void rootExtendedHandler(std::shared_ptr<RLP::Pdu>);
|
||||
void syncPacketHandler(std::shared_ptr<EXTENDED::Pdu>) {};
|
||||
void discoveryPacketHandler(std::shared_ptr<EXTENDED::Pdu>);
|
||||
void discoveryListHanlder(std::shared_ptr<EXTENDED::DISCOVERY::Pdu>);
|
||||
|
||||
private:
|
||||
std::unordered_map <uint16_t, SACN::Universe *> universes_;
|
||||
std::vector<EXTENDED::DISCOVERY::Watcher> discoveryCallbacks_;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue