// hyperion local includes #include "LedDeviceUdpArtNet.h" #ifdef _WIN32 #include #else #include #endif #include const ushort ARTNET_DEFAULT_PORT = 6454; LedDeviceUdpArtNet::LedDeviceUdpArtNet(const QJsonObject &deviceConfig) : ProviderUdp(deviceConfig) { } 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 &ledValues) { int retVal = 0; int thisUniverse = _artnet_universe; const uint8_t * rawdata = reinterpret_cast(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; }