| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of the Falcon Player (FPP) and is Copyright (C) | ||
| 3 | * 2013-2022 by the Falcon Player Developers. | ||
| 4 | * | ||
| 5 | * The Falcon Player (FPP) is free software, and is covered under | ||
| 6 | * multiple Open Source licenses. Please see the included 'LICENSES' | ||
| 7 | * file for descriptions of what files are covered by each license. | ||
| 8 | * | ||
| 9 | * This source file is covered under the GPL v2 as described in the | ||
| 10 | * included LICENSE.GPL file. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "fpp-pch.h" | ||
| 14 | |||
| 15 | #include "fpp-json.h" | ||
| 16 | |||
| 17 | #include <arpa/inet.h> | ||
| 18 | #include <net/if.h> | ||
| 19 | #include <netinet/in.h> | ||
| 20 | #include <sys/ioctl.h> | ||
| 21 | #include <sys/socket.h> | ||
| 22 | #include <sys/time.h> | ||
| 23 | #include <sys/types.h> | ||
| 24 | #include <ctype.h> | ||
| 25 | #include <errno.h> | ||
| 26 | #include <math.h> | ||
| 27 | #include <netdb.h> | ||
| 28 | #include <signal.h> | ||
| 29 | #include <unistd.h> | ||
| 30 | |||
| 31 | #include "../Warnings.h" | ||
| 32 | #include "../log.h" | ||
| 33 | |||
| 34 | #include "ChannelOutputSetup.h" | ||
| 35 | #include "E131.h" | ||
| 36 | #include "Universe.h" | ||
| 37 | #include "channeloutputthread.h" | ||
| 38 | #include "e131defs.h" | ||
| 39 | #include "fpp.h" | ||
| 40 | #include "ping.h" | ||
| 41 | |||
| 42 | const unsigned char E131header[] = { | ||
| 43 | 0x00, 0x10, 0x00, 0x00, 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00, | ||
| 44 | 0x72, 0x6e, 0x00, 0x00, 0x00, 0x04, 'F', 'A', 'L', 'C', 'O', 'N', ' ', 'F', 'P', 'P', | ||
| 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x58, 0x00, 0x00, 0x00, 0x02, 'F', 'A', 'L', 'C', | ||
| 46 | 'O', 'N', 'C', 'H', 'R', 'I', 'S', 'T', 'M', 'A', 'S', '.', 'C', 'O', 'M', ' ', | ||
| 47 | 'B', 'Y', ' ', 'D', 'P', 'I', 'T', 'T', 'S', ' ', 'A', 'N', 'D', ' ', 'M', 'Y', | ||
| 48 | 'K', 'R', 'O', 'F', 'T', ' ', 'F', 'A', 'L', 'C', 'O', 'N', ' ', 'P', 'I', ' ', | ||
| 49 | 'P', 'L', 'A', 'Y', 'E', 'R', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, | ||
| 50 | 0x00, 0x00, 0x01, 0x72, 0x0b, 0x02, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00 | ||
| 51 | }; | ||
| 52 | |||
| 53 | const unsigned char E131SyncHeader[] = { | ||
| 54 | // Root Layer (38 bytes) | ||
| 55 | 0x00, 0x10, // Preamble Size | ||
| 56 | 0x00, 0x00, // Post-amble Size | ||
| 57 | 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00, // "ASC-E1.17\0\0\0" | ||
| 58 | 0x70, 0x21, // RLP Flags + Length (49-16=33) | ||
| 59 | 0x00, 0x00, 0x00, 0x08, // Root Vector = VECTOR_ROOT_E131_EXTENDED | ||
| 60 | 'F', 'A', 'L', 'C', 'O', 'N', ' ', 'F', 'P', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CID | ||
| 61 | // Framing Layer (11 bytes) | ||
| 62 | 0x70, 0x0b, // Framing Flags + Length (49-38=11) | ||
| 63 | 0x00, 0x00, 0x00, 0x01, // Framing Vector = VECTOR_E131_EXTENDED_SYNCHRONIZATION | ||
| 64 | 0x00, // Sequence Number | ||
| 65 | 0x00, 0x00, // Synchronization Address | ||
| 66 | 0x00, 0x00 // Reserved | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const std::string E131TYPE = "e1.31"; | ||
| 70 | |||
| 71 | 8 | const std::string& E131OutputData::GetOutputTypeString() const { | |
| 72 | 8 | return E131TYPE; | |
| 73 | } | ||
| 74 | |||
| 75 | 158 | E131OutputData::E131OutputData(const Json::Value& config) : | |
| 76 | UDPOutputData(config), | ||
| 77 | 158 | universeCount(1), | |
| 78 | 158 | syncUniverse(0), | |
| 79 | 158 | e131SyncPacket(nullptr) { | |
| 80 | sockaddr_in e131Address; | ||
| 81 | 158 | memset((char*)&e131Address, 0, sizeof(sockaddr_in)); | |
| 82 | 158 | e131Address.sin_family = AF_INET; | |
| 83 | 158 | e131Address.sin_port = htons(E131_DEST_PORT); | |
| 84 | |||
| 85 |
2/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✗ Branch 3 not taken.
|
158 | universe = config["id"].asInt(); |
| 86 |
2/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✗ Branch 3 not taken.
|
158 | priority = config["priority"].asInt(); |
| 87 |
3/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 138 times.
|
158 | if (config.isMember("universeCount")) { |
| 88 |
2/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | universeCount = config["universeCount"].asInt(); |
| 89 | } | ||
| 90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
|
158 | if (universeCount < 1) { |
| 91 | ✗ | universeCount = 1; | |
| 92 | } | ||
| 93 |
3/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 155 times.
|
158 | if (config.isMember("syncUniverse")) { |
| 94 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | syncUniverse = config["syncUniverse"].asInt(); |
| 95 | } | ||
| 96 |
2/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 158 times.
|
158 | if (syncUniverse < 0 || syncUniverse > 63999) { |
| 97 | ✗ | syncUniverse = 0; | |
| 98 | } | ||
| 99 |
2/3✓ Branch 0 taken 4 times.
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
158 | switch (type) { |
| 100 | 4 | case 0: // Multicast | |
| 101 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ipAddress = ""; |
| 102 | 4 | break; | |
| 103 | 154 | case 1: //UnicastAddress | |
| 104 |
2/4✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
|
154 | ipAddress = config["address"].asString(); |
| 105 | 154 | break; | |
| 106 | } | ||
| 107 | |||
| 108 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 154 times.
|
158 | if (type == E131_TYPE_MULTICAST) { |
| 109 | int UniverseOctet[2]; | ||
| 110 | char sAddress[32]; | ||
| 111 | |||
| 112 | 4 | UniverseOctet[0] = universe / 256; | |
| 113 | 4 | UniverseOctet[1] = universe % 256; | |
| 114 | 4 | snprintf(sAddress, sizeof(sAddress), "239.255.%d.%d", UniverseOctet[0], UniverseOctet[1]); | |
| 115 | 4 | e131Address.sin_addr.s_addr = inet_addr(sAddress); | |
| 116 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 1 times.
|
154 | } else if (active) { |
| 117 |
1/2✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
|
153 | e131Address.sin_addr.s_addr = toInetAddr(ipAddress, valid); |
| 118 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 142 times.
|
153 | if (!valid) { |
| 119 |
3/6✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
11 | AddOutputConfigWarning(14, "Could not resolve host name " + ipAddress + " - disabling output"); |
| 120 | 11 | active = false; | |
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | e131Iovecs.resize(universeCount * 2); |
| 125 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | e131Headers.resize(universeCount); |
| 126 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | e131SentSequence.assign(universeCount, 0); |
| 127 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | e131Pending.assign(universeCount, false); |
| 128 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | e131Addresses.resize(universeCount); |
| 129 |
2/2✓ Branch 0 taken 2692 times.
✓ Branch 1 taken 158 times.
|
2850 | for (int x = 0; x < universeCount; x++) { |
| 130 |
2/2✓ Branch 0 taken 1503 times.
✓ Branch 1 taken 1189 times.
|
2692 | if (type == E131_TYPE_MULTICAST) { |
| 131 | int UniverseOctet[2]; | ||
| 132 | char sAddress[32]; | ||
| 133 | |||
| 134 | 1503 | int u = universe + x; | |
| 135 | 1503 | UniverseOctet[0] = u / 256; | |
| 136 | 1503 | UniverseOctet[1] = u % 256; | |
| 137 | 1503 | snprintf(sAddress, sizeof(sAddress), "239.255.%d.%d", UniverseOctet[0], UniverseOctet[1]); | |
| 138 | 1503 | e131Address.sin_addr.s_addr = inet_addr(sAddress); | |
| 139 | } | ||
| 140 | 2692 | e131Addresses[x] = e131Address; | |
| 141 | |||
| 142 | 2692 | unsigned char* e131Buffer = (unsigned char*)malloc(E131_HEADER_LENGTH); | |
| 143 | 2692 | e131Headers[x] = e131Buffer; | |
| 144 | 2692 | memcpy(e131Buffer, E131header, E131_HEADER_LENGTH); | |
| 145 | |||
| 146 | 2692 | int uni = universe + x; | |
| 147 | 2692 | e131Buffer[E131_PRIORITY_INDEX] = priority; | |
| 148 | 2692 | e131Buffer[E131_SYNC_ADDRESS_INDEX] = (char)(syncUniverse / 256); | |
| 149 | 2692 | e131Buffer[E131_SYNC_ADDRESS_INDEX + 1] = (char)(syncUniverse % 256); | |
| 150 | 2692 | e131Buffer[E131_UNIVERSE_INDEX] = (char)(uni / 256); | |
| 151 | 2692 | e131Buffer[E131_UNIVERSE_INDEX + 1] = (char)(uni % 256); | |
| 152 | |||
| 153 | // Property Value Count | ||
| 154 | 2692 | e131Buffer[E131_COUNT_INDEX] = ((channelCount + 1) / 256); | |
| 155 | 2692 | e131Buffer[E131_COUNT_INDEX + 1] = ((channelCount + 1) % 256); | |
| 156 | |||
| 157 | // RLP Protocol flags and length | ||
| 158 | 2692 | int count = 638 - 16 - (512 - (channelCount)); | |
| 159 | 2692 | e131Buffer[E131_RLP_COUNT_INDEX] = (count / 256) + 0x70; | |
| 160 | 2692 | e131Buffer[E131_RLP_COUNT_INDEX + 1] = count % 256; | |
| 161 | |||
| 162 | // Framing Protocol flags and length | ||
| 163 | 2692 | count = 638 - 38 - (512 - (channelCount)); | |
| 164 | 2692 | e131Buffer[E131_FRAMING_COUNT_INDEX] = (count / 256) + 0x70; | |
| 165 | 2692 | e131Buffer[E131_FRAMING_COUNT_INDEX + 1] = count % 256; | |
| 166 | |||
| 167 | // DMP Protocol flags and length | ||
| 168 | 2692 | count = 638 - 115 - (512 - (channelCount)); | |
| 169 | 2692 | e131Buffer[E131_DMP_COUNT_INDEX] = (count / 256) + 0x70; | |
| 170 | 2692 | e131Buffer[E131_DMP_COUNT_INDEX + 1] = count % 256; | |
| 171 | |||
| 172 | 2692 | e131Buffer[E131_SEQUENCE_INDEX] = 0; | |
| 173 | |||
| 174 | // use scatter/gather for the packet. One IOV will contain | ||
| 175 | // the header, the second will point into the raw channel data | ||
| 176 | // and will be set at output time. This avoids any memcpy. | ||
| 177 | 2692 | e131Iovecs[x * 2].iov_base = e131Buffer; | |
| 178 | 2692 | e131Iovecs[x * 2].iov_len = E131_HEADER_LENGTH; | |
| 179 | 2692 | e131Iovecs[x * 2 + 1].iov_base = nullptr; | |
| 180 | 2692 | e131Iovecs[x * 2 + 1].iov_len = channelCount; | |
| 181 | } | ||
| 182 | |||
| 183 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 155 times.
|
158 | if (syncUniverse > 0) { |
| 184 | 3 | e131SyncPacket = (unsigned char*)malloc(E131_SYNC_PACKET_LENGTH); | |
| 185 | 3 | memcpy(e131SyncPacket, E131SyncHeader, E131_SYNC_PACKET_LENGTH); | |
| 186 | 3 | e131SyncPacket[E131_SYNC_PACKET_UNIVERSE_INDEX] = (unsigned char)(syncUniverse / 256); | |
| 187 | 3 | e131SyncPacket[E131_SYNC_PACKET_UNIVERSE_INDEX + 1] = (unsigned char)(syncUniverse % 256); | |
| 188 | |||
| 189 | 3 | e131SyncIovec.iov_base = e131SyncPacket; | |
| 190 | 3 | e131SyncIovec.iov_len = E131_SYNC_PACKET_LENGTH; | |
| 191 | |||
| 192 | 3 | memset((char*)&e131SyncAddress, 0, sizeof(sockaddr_in)); | |
| 193 | 3 | e131SyncAddress.sin_family = AF_INET; | |
| 194 | 3 | e131SyncAddress.sin_port = htons(E131_DEST_PORT); | |
| 195 | char sAddress[32]; | ||
| 196 | 3 | snprintf(sAddress, sizeof(sAddress), "239.255.%d.%d", | |
| 197 | 3 | syncUniverse / 256, syncUniverse % 256); | |
| 198 | 3 | e131SyncAddress.sin_addr.s_addr = inet_addr(sAddress); | |
| 199 | } | ||
| 200 | 158 | } | |
| 201 | |||
| 202 | 632 | E131OutputData::~E131OutputData() { | |
| 203 |
2/2✓ Branch 0 taken 2692 times.
✓ Branch 1 taken 158 times.
|
5700 | for (auto a : e131Headers) { |
| 204 | 5384 | free(a); | |
| 205 | } | ||
| 206 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 155 times.
|
316 | if (e131SyncPacket) { |
| 207 | 6 | free(e131SyncPacket); | |
| 208 | } | ||
| 209 | 632 | } | |
| 210 | |||
| 211 | 316 | bool E131OutputData::IsPingable() { | |
| 212 | 316 | return type == 1; | |
| 213 | } | ||
| 214 | |||
| 215 | 20082 | void E131OutputData::PrepareData(unsigned char* channelData, UDPOutputMessages& msgs) { | |
| 216 |
3/6✓ Branch 0 taken 20082 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20082 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20082 times.
✗ Branch 5 not taken.
|
20082 | if (valid && active) { |
| 217 | 20082 | unsigned char* cur = channelData + startChannel - 1; | |
| 218 | 20082 | int start = 0; | |
| 219 | 20082 | bool anySkipped = false; | |
| 220 | 20082 | bool allSkipped = true; | |
| 221 |
2/2✓ Branch 0 taken 702051 times.
✓ Branch 1 taken 20082 times.
|
722133 | for (int x = 0; x < universeCount; x++) { |
| 222 |
2/2✓ Branch 0 taken 701984 times.
✓ Branch 1 taken 67 times.
|
702051 | if (NeedToOutputFrame(channelData, startChannel - 1, start, channelCount)) { |
| 223 | struct mmsghdr msg; | ||
| 224 | 701984 | memset(&msg, 0, sizeof(msg)); | |
| 225 | |||
| 226 | 701984 | msg.msg_hdr.msg_name = &e131Addresses[x]; | |
| 227 | 701984 | msg.msg_hdr.msg_namelen = sizeof(sockaddr_in); | |
| 228 | 701984 | msg.msg_hdr.msg_iov = &e131Iovecs[x * 2]; | |
| 229 | 701984 | msg.msg_hdr.msg_iovlen = 2; | |
| 230 | 701984 | msg.msg_len = channelCount + E131_HEADER_LENGTH; | |
| 231 |
2/2✓ Branch 0 taken 312142 times.
✓ Branch 1 taken 389842 times.
|
701984 | if (type == E131_TYPE_MULTICAST) { |
| 232 |
2/4✓ Branch 0 taken 312142 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 312142 times.
✗ Branch 3 not taken.
|
312142 | msgs[MULTICAST_MESSAGES_KEY].push_back(msg); |
| 233 | } else { | ||
| 234 |
2/4✓ Branch 0 taken 389842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 389842 times.
✗ Branch 3 not taken.
|
389842 | msgs[e131Addresses[x].sin_addr.s_addr].push_back(msg); |
| 235 | } | ||
| 236 | |||
| 237 | 701984 | e131Headers[x][E131_SEQUENCE_INDEX] = e131SentSequence[x] + 1; | |
| 238 |
1/2✓ Branch 0 taken 701984 times.
✗ Branch 1 not taken.
|
701984 | e131Pending[x] = true; |
| 239 | 701984 | e131Iovecs[x * 2 + 1].iov_base = (void*)cur; | |
| 240 | 701984 | allSkipped = false; | |
| 241 | } else { | ||
| 242 |
1/2✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
|
67 | e131Pending[x] = false; |
| 243 | 67 | anySkipped = true; | |
| 244 | } | ||
| 245 | 702051 | cur += channelCount; | |
| 246 | 702051 | start += channelCount; | |
| 247 | } | ||
| 248 |
2/2✓ Branch 0 taken 67 times.
✓ Branch 1 taken 20015 times.
|
20082 | if (anySkipped) { |
| 249 | 67 | skippedFrames++; | |
| 250 | } else { | ||
| 251 | 20015 | skippedFrames = 0; | |
| 252 | } | ||
| 253 |
2/2✓ Branch 0 taken 20015 times.
✓ Branch 1 taken 67 times.
|
20082 | if (!allSkipped) { |
| 254 | 20015 | SaveFrame(&channelData[startChannel - 1], start); | |
| 255 | } | ||
| 256 | } | ||
| 257 | 20082 | } | |
| 258 | |||
| 259 | 20082 | void E131OutputData::PostPrepareData(unsigned char* channelData, UDPOutputMessages& msgs) { | |
| 260 | 20082 | e131SyncPending = false; | |
| 261 |
7/10✓ Branch 0 taken 20082 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20082 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
✓ Branch 5 taken 19936 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 146 times.
✓ Branch 8 taken 19936 times.
✓ Branch 9 taken 146 times.
|
20082 | if (!valid || !active || syncUniverse <= 0 || !e131SyncPacket) { |
| 262 | 19936 | return; | |
| 263 | } | ||
| 264 | |||
| 265 | // If another output already queued a sync packet for this same sync | ||
| 266 | // universe (same destination multicast address), skip to avoid duplicates. | ||
| 267 |
1/2✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
|
146 | auto& syncMsgs = msgs[E131_SYNC_KEY]; |
| 268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
|
146 | for (const auto& existing : syncMsgs) { |
| 269 | ✗ | sockaddr_in* addr = (sockaddr_in*)existing.msg_hdr.msg_name; | |
| 270 | ✗ | if (addr && addr->sin_addr.s_addr == e131SyncAddress.sin_addr.s_addr) { | |
| 271 | ✗ | return; | |
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | 146 | e131SyncPacket[E131_SYNC_PACKET_SEQ_INDEX] = e131SyncSentSequence + 1; | |
| 276 | 146 | e131SyncPending = true; | |
| 277 | |||
| 278 | struct mmsghdr msg; | ||
| 279 | 146 | memset(&msg, 0, sizeof(msg)); | |
| 280 | 146 | msg.msg_hdr.msg_name = &e131SyncAddress; | |
| 281 | 146 | msg.msg_hdr.msg_namelen = sizeof(sockaddr_in); | |
| 282 | 146 | msg.msg_hdr.msg_iov = &e131SyncIovec; | |
| 283 | 146 | msg.msg_hdr.msg_iovlen = 1; | |
| 284 | 146 | msg.msg_len = E131_SYNC_PACKET_LENGTH; | |
| 285 |
1/2✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
|
146 | syncMsgs.push_back(msg); |
| 286 | } | ||
| 287 | |||
| 288 | 20742 | void E131OutputData::FrameSent() { | |
| 289 |
2/2✓ Branch 0 taken 699737 times.
✓ Branch 1 taken 20742 times.
|
720479 | for (int x = 0; x < universeCount; x++) { |
| 290 |
3/4✓ Branch 0 taken 699737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 698775 times.
✓ Branch 3 taken 962 times.
|
699737 | if (e131Pending[x]) { |
| 291 | 698775 | e131SentSequence[x] = e131Headers[x][E131_SEQUENCE_INDEX]; | |
| 292 |
1/2✓ Branch 0 taken 698775 times.
✗ Branch 1 not taken.
|
698775 | e131Pending[x] = false; |
| 293 | } | ||
| 294 | } | ||
| 295 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 20604 times.
|
20742 | if (e131SyncPending) { |
| 296 | 138 | e131SyncSentSequence = e131SyncPacket[E131_SYNC_PACKET_SEQ_INDEX]; | |
| 297 | 138 | e131SyncPending = false; | |
| 298 | } | ||
| 299 | 20742 | } | |
| 300 | |||
| 301 | 281 | void E131OutputData::GetRequiredChannelRange(int& min, int& max) { | |
| 302 | 281 | min = startChannel - 1; | |
| 303 | 281 | max = startChannel + (channelCount * universeCount) - 1; | |
| 304 | 281 | } | |
| 305 | |||
| 306 | 158 | void E131OutputData::DumpConfig() { | |
| 307 | 158 | LogDebug(VB_CHANNELOUT, "E1.31 Universe: %s %d:%d:%d:%d:%d:%d sync:%d %s\n", | |
| 308 | description.c_str(), | ||
| 309 | active, | ||
| 310 | universe, | ||
| 311 | startChannel, | ||
| 312 | channelCount, | ||
| 313 | type, | ||
| 314 | universeCount, | ||
| 315 | syncUniverse, | ||
| 316 | ipAddress.c_str()); | ||
| 317 | 158 | } | |
| 318 |