diff --git a/README.md b/README.md index a6fbe1b..873b899 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ The DmdStreamHeader is defined as a struct: uint16_t width = 0; uint16_t height = 0; uint8_t buffered = 0; // 0 => not buffered, 1 => buffered + uint8_t disconnectOthers = 0; // 0 => no, 1 => yes uint32_t length = 0; }; @@ -121,7 +122,10 @@ grayscale content. So if you want to write a general purpose client to display images or text, you're adviced to use `Mode::RGB24` or `Mode::RGB216`! The `buffered` flag set to `1` means that the current data not just gets displayed, but also buffered for later use. -As soon as some buffered data exists, it will be displayed instead of a black screen if a client disconnects. +As soon as some buffered data exists, it will be displayed instead of a black screen if a client disconnects. + +The `disconnectOthers` flag set to `1` means that any other client get disconnected except the most recent one. +But only the most recent one is allowed to set this flag. ### Notes @@ -139,6 +143,8 @@ To send a RGB24 image of 4x2 pixels, you have to sent these two packages, a head 0x02 0x00 0x00 0x00 // Mode::RGB24 (if your system is big endian, the byte order needs to be swapped) 0x04 0x00 // width 4 (if your system is big endian, the byte order needs to be swapped) 0x02 0x00 // height 2 (if your system is big endian, the byte order needs to be swapped) +0x00 // not buffered +0x00 // don't disconnect others 0x18 0x00 0x00 0x00 // payload length 24 (if your system is big endian, the byte order needs to be swapped) ``` diff --git a/include/DMDUtil/DMD.h b/include/DMDUtil/DMD.h index cb7993b..770cde3 100644 --- a/include/DMDUtil/DMD.h +++ b/include/DMDUtil/DMD.h @@ -103,6 +103,7 @@ class DMDUTILAPI DMD uint16_t width = 0; uint16_t height = 0; uint8_t buffered = 0; // 0 => unbuffered, 1 => buffered + uint8_t disconnectOthers = 0; // 0 => no, 1 => yes uint32_t length = 0; }; diff --git a/src/dmdServer.cpp b/src/dmdServer.cpp index 5bcf96f..414e1f4 100644 --- a/src/dmdServer.cpp +++ b/src/dmdServer.cpp @@ -18,6 +18,7 @@ using namespace std; DMDUtil::DMD* pDmd; uint32_t currentThreadId = 0; +bool disconnectOtherClients = false; std::vector threads; bool opt_verbose = false; bool opt_fixedAltColorPath = false; @@ -74,7 +75,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) DMDUtil::DMD::StreamHeader* pStreamHeader = (DMDUtil::DMD::StreamHeader*)malloc(sizeof(DMDUtil::DMD::StreamHeader)); ssize_t n; - while ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::StreamHeader))) > 0) + while ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::StreamHeader))) > 0 && + (!disconnectOtherClients || threadId == currentThreadId)) { if (n == sizeof(DMDUtil::DMD::StreamHeader)) { @@ -90,6 +92,13 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) if (pStreamHeader->buffered) DMDUtil::Log("Next data will be buffered"); } + // Only the current (most recent) thread is allowed to disconnect other clients. + if (threadId == currentThreadId && pStreamHeader->disconnectOthers) + { + if (opt_verbose) DMDUtil::Log("Other clients will be disconnected"); + disconnectOtherClients = true; + } + switch (pStreamHeader->mode) { case DMDUtil::DMD::Mode::Data: @@ -171,8 +180,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } } - // Display a buffered frame or clear the display. - if (!pDmd->QueueBuffer()) + // Display a buffered frame or clear the display on disconnect of the current thread. + if (threadId == currentThreadId && !pDmd->QueueBuffer()) { // Clear the DMD by sending a black screen. // Fixed dimension of 128x32 should be OK for all devices. @@ -181,7 +190,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } threads.erase(remove(threads.begin(), threads.end(), threadId), threads.end()); - currentThreadId = threads.back(); + currentThreadId = (threads.size() >= 1) ? threads.back() : 0; + if (threads.size() <= 1) disconnectOtherClients = false; free(pStreamHeader); } @@ -297,7 +307,7 @@ int main(int argc, char* argv[]) else { if (opt_verbose) DMDUtil::Log("New DMD client connected"); - currentThreadId = threadId++; + currentThreadId = ++threadId; threads.push_back(currentThreadId); // Create a thread and transfer the new stream to it. thread thr(run, std::move(sock), currentThreadId);