Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions include/DMDUtil/DMD.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
#define DMDUTIL_MAX_PATH_SIZE 256
#define DMDUTIL_MAX_TRANSITIONAL_FRAME_DURATION 25

#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h> // Windows byte-order functions
#else
#include <arpa/inet.h> // Linux/macOS byte-order functions
#endif

#include <atomic>
#include <condition_variable>
#include <cstdint>
Expand Down Expand Up @@ -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<Mode>(ntohl(static_cast<uint32_t>(mode)));
layout = static_cast<AlphaNumericLayout>(ntohl(static_cast<uint32_t>(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<Mode>(htonl(static_cast<uint32_t>(mode)));
copy.layout = static_cast<AlphaNumericLayout>(htonl(static_cast<uint32_t>(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
Expand All @@ -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<Mode>(ntohl(static_cast<uint32_t>(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<Mode>(htonl(static_cast<uint32_t>(mode)));
width = htons(width);
height = htons(height);
length = htonl(length);
}
};

struct PathsHeader
Expand All @@ -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

Expand Down
14 changes: 11 additions & 3 deletions src/DMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -396,13 +401,16 @@ void DMD::QueueUpdate(const std::shared_ptr<Update> 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;
}
Expand Down
21 changes: 16 additions & 5 deletions src/dmdServer.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h> // Windows byte-order functions
#else
#include <arpa/inet.h> // Linux/macOS byte-order functions
#endif

#include <algorithm>
#include <chrono>
#include <iostream>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) &&
Expand All @@ -135,6 +141,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
pathsHeader.name, pathsHeader.altColorPath, pathsHeader.pupVideosPath);
auto data = std::make_shared<DMDUtil::DMD::Update>();
memcpy(data.get(), buffer, n);
data->convertToHostByteOrder();

if (data->width <= DMDSERVER_MAX_WIDTH && data->height <= DMDSERVER_MAX_HEIGHT)
{
Expand Down Expand Up @@ -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);
}
Expand Down