diff --git a/include/DMDUtil/DMD.h b/include/DMDUtil/DMD.h index e636e1c0..0b630b1b 100644 --- a/include/DMDUtil/DMD.h +++ b/include/DMDUtil/DMD.h @@ -15,6 +15,12 @@ #define DMDUTIL_MAX_PATH_SIZE 256 #define DMDUTIL_MAX_TRANSITIONAL_FRAME_DURATION 25 +#if defined(_WIN32) || defined(_WIN64) +#include // Windows byte-order functions +#else +#include // Linux/macOS byte-order functions +#endif + #include #include #include @@ -122,6 +128,44 @@ class DMDUTILAPI DMD uint8_t b; uint16_t width; uint16_t height; + + void convertToHostByteOrder() + { + // uint8_t and bool are not converted, as they are already in host byte order. + mode = static_cast(ntohl(static_cast(mode))); + layout = static_cast(ntohl(static_cast(layout))); + depth = ntohl(depth); + for (size_t i = 0; i < 256 * 64; i++) + { + segData[i] = ntohs(segData[i]); + } + for (size_t i = 0; i < 128; i++) + { + segData2[i] = ntohs(segData2[i]); + } + width = ntohs(width); + height = ntohs(height); + } + + Update toNetworkByteOrder() const + { + // uint8_t and bool are not converted, as they are already in network byte order. + Update copy = *this; + copy.mode = static_cast(htonl(static_cast(mode))); + copy.layout = static_cast(htonl(static_cast(layout))); + copy.depth = htonl(depth); + for (size_t i = 0; i < 256 * 64; i++) + { + copy.segData[i] = htons(segData[i]); + } + for (size_t i = 0; i < 128; i++) + { + copy.segData2[i] = htons(segData2[i]); + } + copy.width = htons(width); + copy.height = htons(height); + return copy; + } }; struct StreamHeader @@ -134,6 +178,24 @@ class DMDUTILAPI DMD uint8_t buffered = 0; // 0 => unbuffered, 1 => buffered uint8_t disconnectOthers = 0; // 0 => no, 1 => yes uint32_t length = 0; + + void convertToHostByteOrder() + { + // uint8_t and char are not converted, as they are already in host byte order. + mode = static_cast(ntohl(static_cast(mode))); + width = ntohs(width); + height = ntohs(height); + length = ntohl(length); + } + + void convertToNetworkByteOrder() + { + // uint8_t and char are not converted, as they are already in network byte order. + mode = static_cast(htonl(static_cast(mode))); + width = htons(width); + height = htons(height); + length = htonl(length); + } }; struct PathsHeader @@ -142,6 +204,10 @@ class DMDUTILAPI DMD char name[DMDUTIL_MAX_NAME_SIZE] = {0}; char altColorPath[DMDUTIL_MAX_PATH_SIZE] = {0}; char pupVideosPath[DMDUTIL_MAX_PATH_SIZE] = {0}; + + void convertToHostByteOrder() {} + + void convertToNetworkByteOrder() {} }; #pragma pack(pop) // Reset to default packing diff --git a/src/DMD.cpp b/src/DMD.cpp index cb90b56f..a11ee935 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -53,7 +53,11 @@ class DMDServerConnector static DMDServerConnector* Create(const char* pAddress, int port) { sockpp::tcp_connector* pConnector = new sockpp::tcp_connector({pAddress, (in_port_t)port}); - return pConnector ? new DMDServerConnector(pConnector) : nullptr; + if (pConnector) + { + return new DMDServerConnector(pConnector); + } + return nullptr; } ssize_t Write(const void* buf, size_t size) { return m_pConnector->write_n(buf, size); } @@ -284,7 +288,8 @@ void DMD::AddRGB24DMD(RGB24DMD* pRGB24DMD) { m_rgb24DMDs.push_back(pRGB24DMD); Log(DMDUtil_LogLevel_INFO, "Added RGB24DMD"); - if (!m_pRGB24DMDThread) { + if (!m_pRGB24DMDThread) + { m_pRGB24DMDThread = new std::thread(&DMD::RGB24DMDThread, this); Log(DMDUtil_LogLevel_INFO, "RGB24DMDThread started"); } @@ -396,13 +401,16 @@ void DMD::QueueUpdate(const std::shared_ptr dmdUpdate, bool buffered) StreamHeader streamHeader; streamHeader.buffered = (uint8_t)buffered; streamHeader.disconnectOthers = (uint8_t)m_dmdServerDisconnectOthers; + streamHeader.convertToNetworkByteOrder(); m_pDMDServerConnector->Write(&streamHeader, sizeof(StreamHeader)); PathsHeader pathsHeader; strcpy(pathsHeader.name, m_romName); strcpy(pathsHeader.altColorPath, m_altColorPath); strcpy(pathsHeader.pupVideosPath, m_pupVideosPath); + pathsHeader.convertToNetworkByteOrder(); m_pDMDServerConnector->Write(&pathsHeader, sizeof(PathsHeader)); - m_pDMDServerConnector->Write(dmdUpdate.get(), sizeof(Update)); + Update dmdUpdateNetwork = dmdUpdate->toNetworkByteOrder(); + m_pDMDServerConnector->Write(&dmdUpdateNetwork, sizeof(Update)); if (streamHeader.disconnectOthers != 0) m_dmdServerDisconnectOthers = false; } diff --git a/src/dmdServer.cpp b/src/dmdServer.cpp index 7663baf9..96c7d79c 100644 --- a/src/dmdServer.cpp +++ b/src/dmdServer.cpp @@ -1,3 +1,9 @@ +#if defined(_WIN32) || defined(_WIN64) +#include // Windows byte-order functions +#else +#include // Linux/macOS byte-order functions +#endif + #include #include #include @@ -94,9 +100,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) if (n == sizeof(DMDUtil::DMD::StreamHeader)) { - // At the moment the server only listens on localhost. - // Therefore, we don't have to take care about litte vs. big endian and can use memcpy. memcpy(pStreamHeader, buffer, n); + pStreamHeader->convertToHostByteOrder(); if (strcmp(pStreamHeader->header, "DMDStream") == 0 && pStreamHeader->version == 1) { if (opt_verbose) @@ -124,6 +129,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) { DMDUtil::DMD::PathsHeader pathsHeader; memcpy(&pathsHeader, buffer, n); + pathsHeader.convertToHostByteOrder(); if (strcmp(pathsHeader.header, "Paths") == 0 && (n = sock.read_n(buffer, sizeof(DMDUtil::DMD::Update))) == sizeof(DMDUtil::DMD::Update) && @@ -135,6 +141,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) pathsHeader.name, pathsHeader.altColorPath, pathsHeader.pupVideosPath); auto data = std::make_shared(); memcpy(data.get(), buffer, n); + data->convertToHostByteOrder(); if (data->width <= DMDSERVER_MAX_WIDTH && data->height <= DMDSERVER_MAX_HEIGHT) { @@ -165,9 +172,13 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) threadId == currentThreadId && pStreamHeader->width <= DMDSERVER_MAX_WIDTH && pStreamHeader->height <= DMDSERVER_MAX_HEIGHT) { - // At the moment the server only listens on localhost. - // Therefore, we don't have to take care about litte vs. big endian and can use the buffer as uint16_t as - // it is. + uint16_t* pixelData = (uint16_t*)buffer; + size_t pixelCount = pStreamHeader->length / sizeof(uint16_t); + for (size_t i = 0; i < pixelCount; i++) + { + pixelData[i] = ntohs(pixelData[i]); + } + pDmd->UpdateRGB16Data((uint16_t*)buffer, pStreamHeader->width, pStreamHeader->height, pStreamHeader->buffered == 1); }