diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 1651771..bee34d9 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -272,3 +272,50 @@ void CommandDistributor::broadcastRaw(clientType type, char * msg) { void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter, int16_t dcAddr) { broadcastReply(COMMAND_TYPE, format,trackLetter, dcAddr); } + +Print * CommandDistributor::getVirtualLCDSerial(byte screen, byte row) { + Print * stream=virtualLCDSerial; + #ifdef CD_HANDLE_RING + rememberVLCDClient=RingStream::NO_CLIENT; + if (!stream && virtualLCDClient!=RingStream::NO_CLIENT) { + // If we are broadcasting from a wifi/eth process we need to complete its output + // before merging broadcasts in the ring, then reinstate it in case + // the process continues to output to its client. + if ((rememberVLCDClient = ring->peekTargetMark()) != RingStream::NO_CLIENT) { + ring->commit(); + } + ring->mark(virtualLCDClient); + stream=ring; + } + #endif + if (stream) StringFormatter::send(stream,F("<@ %d %d \""), screen,row); + return stream; +} + +void CommandDistributor::commitVirtualLCDSerial() { + #ifdef CD_HANDLE_RING + if (virtualLCDClient!=RingStream::NO_CLIENT) { + StringFormatter::send(ring,F("\">\n")); + ring->commit(); + if (rememberVLCDClient!=RingStream::NO_CLIENT) ring->mark(rememberVLCDClient); + return; + } + #endif + StringFormatter::send(virtualLCDSerial,F("\">\n")); +} + +void CommandDistributor::setVirtualLCDSerial(Print * stream) { + #ifdef CD_HANDLE_RING + virtualLCDClient=RingStream::NO_CLIENT; + if (stream && stream->availableForWrite()==RingStream::THIS_IS_A_RINGSTREAM) { + virtualLCDClient=((RingStream *) stream)->peekTargetMark(); + virtualLCDSerial=nullptr; + return; + } + #endif + virtualLCDSerial=stream; +} + +Print* CommandDistributor::virtualLCDSerial=nullptr; +byte CommandDistributor::virtualLCDClient=0xFF; +byte CommandDistributor::rememberVLCDClient=0; \ No newline at end of file diff --git a/CommandDistributor.h b/CommandDistributor.h index d54ef31..43f4b09 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -59,6 +59,14 @@ public : template static void broadcastReply(clientType type, Targs... msg); static void forget(byte clientId); + // Handling code for virtual LCD receiver. + static Print * getVirtualLCDSerial(byte screen, byte row); + static void commitVirtualLCDSerial(); + static void setVirtualLCDSerial(Print * stream); + private: + static Print * virtualLCDSerial; + static byte virtualLCDClient; + static byte rememberVLCDClient; }; #endif diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index d79136f..96bf4c7 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -913,6 +913,13 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'L': // LCC interface implemented in EXRAIL parser break; // Will if not intercepted by EXRAIL + case '@': // JMRI saying "give me virtual LCD msgs" + CommandDistributor::setVirtualLCDSerial(stream); + StringFormatter::send(stream, + F("<@ 0 0 \"DCC-EX v" VERSION "\">\n" + "<@ 0 1 \"Lic GPLv3\">\n")); + return; + default: //anything else will diagnose and drop out to DIAG(F("Opcode=%c params=%d"), opcode, params); for (int i = 0; i < params; i++)