hyperion.ng/libsrc/leddevice/dev_net/LedDeviceUdpArtNet.cpp
2020-08-08 13:09:15 +02:00

109 lines
2.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// hyperion local includes
#include "LedDeviceUdpArtNet.h"
#ifdef _WIN32
#include <winsock.h>
#else
#include <arpa/inet.h>
#endif
#include <QHostInfo>
const ushort ARTNET_DEFAULT_PORT = 6454;
LedDeviceUdpArtNet::LedDeviceUdpArtNet(const QJsonObject &deviceConfig)
: ProviderUdp()
{
_devConfig = deviceConfig;
_isDeviceReady = false;
_activeDeviceType = deviceConfig["type"].toString("UNSPECIFIED").toLower();
}
LedDevice* LedDeviceUdpArtNet::construct(const QJsonObject &deviceConfig)
{
return new LedDeviceUdpArtNet(deviceConfig);
}
bool LedDeviceUdpArtNet::init(const QJsonObject &deviceConfig)
{
bool isInitOK = false;
_port = ARTNET_DEFAULT_PORT;
// Initialise sub-class
if ( ProviderUdp::init(deviceConfig) )
{
_artnet_universe = deviceConfig["universe"].toInt(1);
_artnet_channelsPerFixture = deviceConfig["channelsPerFixture"].toInt(3);
isInitOK = true;
}
return isInitOK;
}
// populates the headers
void LedDeviceUdpArtNet::prepare(unsigned this_universe, unsigned this_sequence, unsigned this_dmxChannelCount)
{
// WTF? why do the specs say:
// "This value should be an even number in the range 2 512. "
if (this_dmxChannelCount & 0x1)
{
this_dmxChannelCount++;
}
memcpy (artnet_packet.ID, "Art-Net\0", 8);
artnet_packet.OpCode = htons(0x0050); // OpOutput / OpDmx
artnet_packet.ProtVer = htons(0x000e);
artnet_packet.Sequence = this_sequence;
artnet_packet.Physical = 0;
artnet_packet.SubUni = this_universe & 0xff ;
artnet_packet.Net = (this_universe >> 8) & 0x7f;
artnet_packet.Length = htons(this_dmxChannelCount);
}
int LedDeviceUdpArtNet::write(const std::vector<ColorRgb> &ledValues)
{
int retVal = 0;
int thisUniverse = _artnet_universe;
const uint8_t * rawdata = reinterpret_cast<const uint8_t *>(ledValues.data());
/*
This field is incremented in the range 0x01 to 0xff to allow the receiving node to resequence packets.
The Sequence field is set to 0x00 to disable this feature.
*/
if (_artnet_seq++ == 0)
{
_artnet_seq = 1;
}
int dmxIdx = 0; // offset into the current dmx packet
memset(artnet_packet.raw, 0, sizeof(artnet_packet.raw));
for (unsigned int ledIdx = 0; ledIdx < _ledRGBCount; ledIdx++)
{
artnet_packet.Data[dmxIdx++] = rawdata[ledIdx];
if ( (ledIdx % 3 == 2) && (ledIdx > 0) )
{
dmxIdx += (_artnet_channelsPerFixture-3);
}
// is this the last byte of last packet || last byte of other packets
if ( (ledIdx == _ledRGBCount-1) || (dmxIdx >= DMX_MAX) )
{
prepare(thisUniverse, _artnet_seq, dmxIdx);
retVal &= writeBytes(18 + qMin(dmxIdx, DMX_MAX), artnet_packet.raw);
memset(artnet_packet.raw, 0, sizeof(artnet_packet.raw));
thisUniverse ++;
dmxIdx = 0;
}
}
return retVal;
}