From 78cc4b9692fb2a90b14505fb95152831d98c8b6b Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sat, 15 Dec 2018 21:03:15 +0200 Subject: [PATCH 01/86] Added overload of Write() with void Write(ola::io::ByteString) This will probably replace Write(DmxBuffer) in the future and maybe should return bool. --- plugins/ftdidmx/FtdiWidget.cpp | 13 +++++++++++++ plugins/ftdidmx/FtdiWidget.h | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 384ed20381..13192611d2 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -53,6 +53,9 @@ #include "ola/BaseTypes.h" #include "ola/StringUtils.h" #include "ola/Constants.h" +#include "ola/rdm/RDMCommand.h" + + #include "plugins/ftdidmx/FtdiWidget.h" namespace ola { @@ -364,6 +367,16 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { } } + +void FtdiInterface::Write(ola::io::ByteString *request) { + if(ftdi_write_data(&m_handle, request->data(), request->size()) < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + } else { + + } +} + bool FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); if (read <= 0) { diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 2f856e5f2b..2f14661704 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -224,9 +224,12 @@ class FtdiInterface { /** @brief Toggle communications line BREAK condition on/off */ bool SetBreak(bool on); - /** @brief Write data to a previously-opened line */ + /** @brief Write data to a previously-opened line, DMX only */ bool Write(const ola::DmxBuffer &data); + /** @brief Write prepared packets to previously opened line, agnostic to packet contents */ + void Write(ola::io::ByteString *request); + /** @brief Read data from a previously-opened line */ bool Read(unsigned char* buff, int size); From e1869e3f2b6b958296306342acb3f0a137280787 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sat, 15 Dec 2018 21:05:34 +0200 Subject: [PATCH 02/86] Indicate that RDM is supported --- plugins/ftdidmx/FtdiDmxPort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 5eb3208c92..6986b43c25 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -45,7 +45,7 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { FtdiInterface *interface, unsigned int id, unsigned int freq) - : BasicOutputPort(parent, id), + : BasicOutputPort(parent, id, true, true), m_interface(interface), m_thread(interface, freq) { m_thread.Start(); From 2b5a5fa061a786cb974534c7d7bcfec9e76be678 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sat, 15 Dec 2018 21:06:20 +0200 Subject: [PATCH 03/86] Initial attempt at adding queue for RDM commands, also added destructor logic to prevent memory leaks (I hope). --- plugins/ftdidmx/FtdiDmxThread.cpp | 26 ++++++++++++++++++++++---- plugins/ftdidmx/FtdiDmxThread.h | 12 ++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index c31be8b898..9088846c80 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -27,10 +27,16 @@ #include #include +#include +#include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/StringUtils.h" +#include "ola/rdm/RDMCommand.h" +#include "ola/rdm/RDMControllerInterface.h" +#include "ola/rdm/RDMCommandSerializer.h" + #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" @@ -54,9 +60,12 @@ FtdiDmxThread::~FtdiDmxThread() { * @brief Stop this thread */ bool FtdiDmxThread::Stop() { - { - ola::thread::MutexLocker locker(&m_term_mutex); - m_term = true; + ola::thread::MutexLocker locker(&m_term_mutex); + m_term = true; + while(!m_RDMQueue.empty()){ + delete m_RDMQueue.front().first; + delete m_RDMQueue.front().second; + m_RDMQueue.pop(); } return Join(); } @@ -73,12 +82,21 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { } } +void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, + ola::rdm::RDMCallback *callback) { + ola::io::ByteString data; + if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*request, &data)) { + OLA_WARN << "RDMCommandSerializer failed."; + } + m_RDMQueue.push(std::pair(&data, callback)); +}; /** * @brief The method called by the thread */ void *FtdiDmxThread::Run() { - TimeStamp ts1, ts2, ts3; + TimeStamp ts1, ts2, ts3, lastDMX; Clock clock; CheckTimeGranularity(); DmxBuffer buffer; diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 26f767e40f..9be591aa81 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -26,8 +26,13 @@ #ifndef PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ #define PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ +#include +#include + #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" +#include "ola/rdm/RDMCommand.h" + namespace ola { namespace plugin { @@ -41,6 +46,9 @@ class FtdiDmxThread : public ola::thread::Thread { bool Stop(); void *Run(); bool WriteDMX(const DmxBuffer &buffer); + void SendRDMRequest(ola::rdm::RDMRequest *request, + ola::rdm::RDMCallback *callback); + bool SupportsRDM() { return true; } private: enum TimerGranularity { UNKNOWN, GOOD, BAD }; @@ -49,10 +57,14 @@ class FtdiDmxThread : public ola::thread::Thread { FtdiInterface *m_interface; bool m_term; unsigned int m_frequency; + DmxBuffer m_buffer; ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; + std::queue> m_RDMQueue; + void CheckTimeGranularity(); static const uint32_t DMX_MAB = 16; From 3b6cb830517358018e7ec9d3de69ccc80d7588c9 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 19 Dec 2018 12:38:40 +0200 Subject: [PATCH 04/86] This a totally disgusting in-between state of the code, I'm about to rewrite/undo a lot of my changes but figure I should maintain stuff just in case. --- plugins/ftdidmx/FtdiDmxPort.h | 93 +++++++++++++++++++++++++++++-- plugins/ftdidmx/FtdiDmxThread.cpp | 74 ++++++++++++++++++++---- plugins/ftdidmx/FtdiDmxThread.h | 3 +- plugins/ftdidmx/FtdiWidget.cpp | 23 ++++---- plugins/ftdidmx/FtdiWidget.h | 4 +- 5 files changed, 167 insertions(+), 30 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 6986b43c25..3328d13605 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -29,8 +29,12 @@ #include #include "ola/DmxBuffer.h" +#include "ola/rdm/DiscoveryAgent.h" +#include "ola/rdm/RDMResponseCodes.h" + #include "olad/Port.h" #include "olad/Preferences.h" + #include "plugins/ftdidmx/FtdiDmxDevice.h" #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" @@ -39,15 +43,23 @@ namespace ola { namespace plugin { namespace ftdidmx { -class FtdiDmxOutputPort : public ola::BasicOutputPort { +class FtdiDmxOutputPort + : public ola::BasicOutputPort, + public ola::rdm::DiscoveryTargetInterface { public: FtdiDmxOutputPort(FtdiDmxDevice *parent, FtdiInterface *interface, unsigned int id, unsigned int freq) - : BasicOutputPort(parent, id, true, true), + : BasicOutputPort(parent, id, false, true), m_interface(interface), - m_thread(interface, freq) { + m_thread(interface, freq), + m_transaction_number(0), + m_discovery_agent(this), + m_uid(0x7a7012345678), + m_mute_complete(nullptr), + m_unmute_complete(nullptr), + m_branch_callback(nullptr) { m_thread.Start(); } ~FtdiDmxOutputPort() { @@ -59,11 +71,84 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { return m_thread.WriteDMX(buffer); } + void SendRDMRequest(ola::rdm::RDMRequest *request, + ola::rdm::RDMCallback *callback) { + request->SetTransactionNumber(m_transaction_number++); + m_thread.SendRDMRequest(request, callback); + } + std::string Description() const { return m_interface->Description(); } - private: + void on_mute_reply(RDMReply *mute_reply) { + MuteDeviceCallback *my_mute_complete = m_mute_complete; + m_mute_complete = nullptr; + //if(mute_reply->Response().SourceUID() == ) + my_mute_complete->Run(true); + } + + void on_unmute_complete(RDMReply *unmute_reply) { + UnMuteDeviceCallback *my_unmute_complete = m_unmute_complete; + m_unmute_complete = nullptr; + ola::rdm::rdm_response_code response = unmute_reply->StatusCode(); + if(response == rdm::RDM_WAS_BROADCAST || response == rdm::RDM_COMPLETED_OK) { + my_unmute_complete->Run(); + } else { + OLA_WARN << "Something went wrong broadcasting unmute"; + my_unmute_complete->Run(); + } + } + + void on_branch_callback(RDMReply *branch_reply) { + BranchCallback *my_branch_callback = m_branch_callback; + m_branch_callback = nullptr; + my_branch_callback->Run(branch_reply->frame().data, branch_reply->frame().length); + } + + void MuteDevice(const ola::rdm::UID &target, + MuteDeviceCallback *mute_complete){ + if(m_mute_complete == nullptr) { + m_mute_complete = mute_complete; + m_thread.SendRDMRequest(ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number++), + &on_mute_reply); + } else { + //fail + } + } + void UnMuteAll(UnMuteDeviceCallback *unmute_complete) { + if(m_unmute_complete == nullptr) { + m_unmute_complete = unmute_complete; + m_thread.SendRDMRequest(ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), + m_transaction_number++), + [&FtdiDmxOutputPort](RDMRequest*) { return on_unmute_complete(RDMReply *unmute_reply)) }; + } else { + //fail + } + } + void Branch(const ola::rdm::UID &lower, + const ola::rdm::UID &upper, + BranchCallback *callback) { + if(m_branch_callback == nullptr) { + m_branch_callback = callback; + m_thread.SendRDMRequest(ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, + m_transaction_number++), + &on_branch_callback); + } else { + //fail + } + } + + private: FtdiInterface *m_interface; FtdiDmxThread m_thread; + + uint8_t m_transaction_number; + ola::rdm::DiscoveryAgent m_discovery_agent; + const ola::rdm::UID m_uid; + + MuteDeviceCallback *m_mute_complete; + UnMuteDeviceCallback * m_unmute_complete; + BranchCallback * m_branch_callback; + }; } // namespace ftdidmx } // namespace plugin diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 9088846c80..80f6e6a768 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -33,9 +33,11 @@ #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/StringUtils.h" + #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/RDMCommandSerializer.h" +#include "ola/rdm/RDMResponseCodes.h" #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" @@ -63,8 +65,9 @@ bool FtdiDmxThread::Stop() { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; while(!m_RDMQueue.empty()){ - delete m_RDMQueue.front().first; - delete m_RDMQueue.front().second; + OLA_INFO << "Emptying Queue"; + //delete m_RDMQueue.front().first; + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); m_RDMQueue.pop(); } return Join(); @@ -84,12 +87,8 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { - ola::io::ByteString data; - if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*request, &data)) { - OLA_WARN << "RDMCommandSerializer failed."; - } - m_RDMQueue.push(std::pair(&data, callback)); + m_RDMQueue.push(std::pair(request, callback)); }; /** @@ -100,6 +99,12 @@ void *FtdiDmxThread::Run() { Clock clock; CheckTimeGranularity(); DmxBuffer buffer; + bool sendRDM = false; + TimeInterval elapsed, interval; + int readBytes; + unsigned char readBuffer[258]; + ola::io::ByteString packetBuffer; + int frameTime = static_cast(floor( (static_cast(1000) / m_frequency) + static_cast(0.5))); @@ -123,6 +128,21 @@ void *FtdiDmxThread::Run() { } clock.CurrentTime(&ts1); + if(!m_RDMQueue.empty()) { + elapsed = ts1 - lastDMX; + if(elapsed.InMilliSeconds() < 500) { + if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_RDMQueue.front().first, &packetBuffer)) { + OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; + delete m_RDMQueue.front().first; + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); + m_RDMQueue.pop(); + sendRDM = false; + } else { + sendRDM = true; + } + } + } + if (!m_interface->SetBreak(true)) { goto framesleep; @@ -140,14 +160,46 @@ void *FtdiDmxThread::Run() { usleep(DMX_MAB); } - if (!m_interface->Write(buffer)) { + if(!sendRDM) { + if (!m_interface->Write(buffer)) { + goto framesleep; + } else { + clock.CurrentTime(&lastDMX); + } + } else { + if(m_interface->Write(&packetBuffer)) { + if(m_RDMQueue.front().first->IsDUB()) { + usleep(1400); + readBytes = m_interface->Read(readBuffer, 258); + if(readBytes <= 0) { // also catches hw issues, slightly incorrect, but they were already reported at hw layer. + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_TIMEOUT); + } else if (readBytes <= 24) {// Ignores potential for bad splitters dropping preamble bytes. + m_RDMQueue.front().second->Run(rdm::RDMReply::DUBReply(rdm::RDMFrame(readBuffer, readBytes))); + } else { + // Invalid response (collision) + } + } else if(!m_RDMQueue.front().first->DestinationUID().IsBroadcast()) { + usleep(31000); // Wait half the time needed for broadcasting 512 bytes (full packet which is impossible in RDM) + readBytes = m_interface->Read(readBuffer, 258); + if(readBytes <= 0) { // also catches hw issues, slightly incorrect, but they were already reported at hw layer. + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_TIMEOUT); + } else { + m_RDMQueue.front().second->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_RDMQueue.front().first)); + } + } else { + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_WAS_BROADCAST); + } + } else { + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); + } + m_RDMQueue.pop(); goto framesleep; } framesleep: // Sleep for the remainder of the DMX frame time clock.CurrentTime(&ts2); - TimeInterval elapsed = ts2 - ts1; + elapsed = ts2 - ts1; if (m_granularity == GOOD) { while (elapsed.InMilliSeconds() < frameTime) { @@ -159,7 +211,7 @@ void *FtdiDmxThread::Run() { // See if we can drop out of bad mode. usleep(1000); clock.CurrentTime(&ts3); - TimeInterval interval = ts3 - ts2; + interval = ts3 - ts2; if (interval.InMilliSeconds() < BAD_GRANULARITY_LIMIT) { m_granularity = GOOD; OLA_INFO << "Switching from BAD to GOOD granularity for ftdi thread"; diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 9be591aa81..3a55ad732e 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -48,7 +48,6 @@ class FtdiDmxThread : public ola::thread::Thread { bool WriteDMX(const DmxBuffer &buffer); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); - bool SupportsRDM() { return true; } private: enum TimerGranularity { UNKNOWN, GOOD, BAD }; @@ -62,7 +61,7 @@ class FtdiDmxThread : public ola::thread::Thread { ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; - std::queue> m_RDMQueue; void CheckTimeGranularity(); diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 13192611d2..74601c2cab 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -368,23 +368,24 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { } -void FtdiInterface::Write(ola::io::ByteString *request) { - if(ftdi_write_data(&m_handle, request->data(), request->size()) < 0) { - OLA_WARN << m_parent->Description() << " " - << ftdi_get_error_string(&m_handle); - } else { - - } +bool FtdiInterface::Write(ola::io::ByteString *packet) { + if(ftdi_write_data(&m_handle, packet->data(), packet->size()) < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + return false; + } else { + return true; + } } -bool FtdiInterface::Read(unsigned char *buff, int size) { +int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); - if (read <= 0) { + if (read < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); - return false; + return read; } else { - return true; + return read; } } diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 2f14661704..dbcd46e3e6 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -228,10 +228,10 @@ class FtdiInterface { bool Write(const ola::DmxBuffer &data); /** @brief Write prepared packets to previously opened line, agnostic to packet contents */ - void Write(ola::io::ByteString *request); + bool Write(ola::io::ByteString *packet); /** @brief Read data from a previously-opened line */ - bool Read(unsigned char* buff, int size); + int Read(unsigned char* buff, int size); /** @brief Setup device for DMX Output **/ bool SetupOutput(); From c51928e7df2d4ebc14bd715b0db83c203b1f62fc Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 20 Dec 2018 00:20:49 +0200 Subject: [PATCH 05/86] Initial compiling version that implements a RDM discoverable target for ftdidmx, code still very ugly and hacky and olad doesn't shut down properly. --- OLA.config | 2 + OLA.creator | 1 + OLA.files | 1080 +++++++++++++++++++++++++++++ OLA.includes | 69 ++ plugins/ftdidmx/FtdiDmxPort.h | 70 +- plugins/ftdidmx/FtdiDmxThread.cpp | 93 ++- plugins/ftdidmx/FtdiDmxThread.h | 25 +- 7 files changed, 1264 insertions(+), 76 deletions(-) create mode 100644 OLA.config create mode 100644 OLA.creator create mode 100644 OLA.files create mode 100644 OLA.includes diff --git a/OLA.config b/OLA.config new file mode 100644 index 0000000000..e0284f4257 --- /dev/null +++ b/OLA.config @@ -0,0 +1,2 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 diff --git a/OLA.creator b/OLA.creator new file mode 100644 index 0000000000..e94cbbd302 --- /dev/null +++ b/OLA.creator @@ -0,0 +1 @@ +[General] diff --git a/OLA.files b/OLA.files new file mode 100644 index 0000000000..ead319fcc8 --- /dev/null +++ b/OLA.files @@ -0,0 +1,1080 @@ +common/base/Credentials.cpp +common/base/CredentialsTest.cpp +common/base/Env.cpp +common/base/Flags.cpp +common/base/FlagsTest.cpp +common/base/Init.cpp +common/base/Logging.cpp +common/base/LoggingTest.cpp +common/base/SysExits.cpp +common/base/Version.cpp +common/dmx/RunLengthEncoder.cpp +common/dmx/RunLengthEncoderTest.cpp +common/export_map/ExportMap.cpp +common/export_map/ExportMapTest.cpp +common/file/Util.cpp +common/file/UtilTest.cpp +common/http/HTTPServer.cpp +common/http/OlaHTTPServer.cpp +common/io/Descriptor.cpp +common/io/DescriptorTest.cpp +common/io/EPoller.cpp +common/io/EPoller.h +common/io/ExtendedSerial.cpp +common/io/IOQueue.cpp +common/io/IOQueueTest.cpp +common/io/IOStack.cpp +common/io/IOStackTest.cpp +common/io/IOUtils.cpp +common/io/InputStreamTest.cpp +common/io/KQueuePoller.cpp +common/io/KQueuePoller.h +common/io/MemoryBlockTest.cpp +common/io/NonBlockingSender.cpp +common/io/OutputStreamTest.cpp +common/io/PollerInterface.cpp +common/io/PollerInterface.h +common/io/SelectPoller.cpp +common/io/SelectPoller.h +common/io/SelectServer.cpp +common/io/SelectServerTest.cpp +common/io/SelectServerThreadTest.cpp +common/io/Serial.cpp +common/io/StdinHandler.cpp +common/io/TimeoutManager.cpp +common/io/TimeoutManager.h +common/io/TimeoutManagerTest.cpp +common/io/WindowsPoller.cpp +common/io/WindowsPoller.h +common/math/Random.cpp +common/messaging/Descriptor.cpp +common/messaging/DescriptorTest.cpp +common/messaging/Message.cpp +common/messaging/MessagePrinter.cpp +common/messaging/MessagePrinterTest.cpp +common/messaging/SchemaPrinter.cpp +common/messaging/SchemaPrinterTest.cpp +common/network/AdvancedTCPConnector.cpp +common/network/AdvancedTCPConnectorTest.cpp +common/network/FakeInterfacePicker.h +common/network/HealthCheckedConnection.cpp +common/network/HealthCheckedConnectionTest.cpp +common/network/IPV4Address.cpp +common/network/IPV4AddressTest.cpp +common/network/Interface.cpp +common/network/InterfacePicker.cpp +common/network/InterfacePickerTest.cpp +common/network/InterfaceTest.cpp +common/network/MACAddress.cpp +common/network/MACAddressTest.cpp +common/network/NetworkUtils.cpp +common/network/NetworkUtilsInternal.h +common/network/NetworkUtilsTest.cpp +common/network/PosixInterfacePicker.cpp +common/network/PosixInterfacePicker.h +common/network/Socket.cpp +common/network/SocketAddress.cpp +common/network/SocketAddressTest.cpp +common/network/SocketCloser.cpp +common/network/SocketHelper.cpp +common/network/SocketHelper.h +common/network/SocketTest.cpp +common/network/TCPConnector.cpp +common/network/TCPConnectorTest.cpp +common/network/TCPSocket.cpp +common/network/WindowsInterfacePicker.cpp +common/network/WindowsInterfacePicker.h +common/protocol/Ola.pb.cc +common/protocol/Ola.pb.h +common/protocol/OlaService.pb.cpp +common/protocol/OlaService.pb.h +common/rdm/AckTimerResponder.cpp +common/rdm/AdvancedDimmerResponder.cpp +common/rdm/CommandPrinter.cpp +common/rdm/DescriptorConsistencyChecker.cpp +common/rdm/DescriptorConsistencyChecker.h +common/rdm/DescriptorConsistencyCheckerTest.cpp +common/rdm/DimmerResponder.cpp +common/rdm/DimmerRootDevice.cpp +common/rdm/DimmerSubDevice.cpp +common/rdm/DiscoveryAgent.cpp +common/rdm/DiscoveryAgentTest.cpp +common/rdm/DiscoveryAgentTestHelper.h +common/rdm/DummyResponder.cpp +common/rdm/FakeNetworkManager.cpp +common/rdm/FakeNetworkManager.h +common/rdm/GroupSizeCalculator.cpp +common/rdm/GroupSizeCalculator.h +common/rdm/GroupSizeCalculatorTest.cpp +common/rdm/MessageDeserializer.cpp +common/rdm/MessageDeserializerTest.cpp +common/rdm/MessageSerializer.cpp +common/rdm/MessageSerializerTest.cpp +common/rdm/MovingLightResponder.cpp +common/rdm/NetworkManager.cpp +common/rdm/NetworkManager.h +common/rdm/NetworkResponder.cpp +common/rdm/OpenLightingEnums.cpp +common/rdm/PidStore.cpp +common/rdm/PidStoreHelper.cpp +common/rdm/PidStoreLoader.cpp +common/rdm/PidStoreLoader.h +common/rdm/PidStoreTest.cpp +common/rdm/Pids.pb.cc +common/rdm/Pids.pb.h +common/rdm/QueueingRDMController.cpp +common/rdm/QueueingRDMControllerTest.cpp +common/rdm/RDMAPI.cpp +common/rdm/RDMAPITest.cpp +common/rdm/RDMCommand.cpp +common/rdm/RDMCommandSerializer.cpp +common/rdm/RDMCommandSerializerTest.cpp +common/rdm/RDMCommandTest.cpp +common/rdm/RDMFrame.cpp +common/rdm/RDMFrameTest.cpp +common/rdm/RDMHelper.cpp +common/rdm/RDMHelperTest.cpp +common/rdm/RDMMessageInterationTest.cpp +common/rdm/RDMReply.cpp +common/rdm/RDMReplyTest.cpp +common/rdm/ResponderHelper.cpp +common/rdm/ResponderLoadSensor.cpp +common/rdm/ResponderPersonality.cpp +common/rdm/ResponderSettings.cpp +common/rdm/ResponderSlotData.cpp +common/rdm/SensorResponder.cpp +common/rdm/StringMessageBuilder.cpp +common/rdm/StringMessageBuilderTest.cpp +common/rdm/SubDeviceDispatcher.cpp +common/rdm/TestHelper.h +common/rdm/UID.cpp +common/rdm/UIDAllocatorTest.cpp +common/rdm/UIDTest.cpp +common/rdm/VariableFieldSizeCalculator.cpp +common/rdm/VariableFieldSizeCalculator.h +common/rdm/VariableFieldSizeCalculatorTest.cpp +common/rpc/Rpc.pb.cc +common/rpc/Rpc.pb.h +common/rpc/RpcChannel.cpp +common/rpc/RpcChannel.h +common/rpc/RpcChannelTest.cpp +common/rpc/RpcController.cpp +common/rpc/RpcController.h +common/rpc/RpcControllerTest.cpp +common/rpc/RpcHeader.h +common/rpc/RpcHeaderTest.cpp +common/rpc/RpcPeer.h +common/rpc/RpcServer.cpp +common/rpc/RpcServer.h +common/rpc/RpcServerTest.cpp +common/rpc/RpcService.h +common/rpc/RpcSession.h +common/rpc/TestService.cpp +common/rpc/TestService.h +common/rpc/TestService.pb.cc +common/rpc/TestService.pb.h +common/rpc/TestServiceService.pb.cpp +common/rpc/TestServiceService.pb.h +common/strings/Format.cpp +common/strings/Utils.cpp +common/strings/UtilsTest.cpp +common/system/Limits.cpp +common/system/SystemUtils.cpp +common/testing/GenericTester.cpp +common/testing/MockUDPSocket.cpp +common/testing/TestUtils.cpp +common/thread/ConsumerThread.cpp +common/thread/ExecutorThread.cpp +common/thread/ExecutorThreadTest.cpp +common/thread/FutureTest.cpp +common/thread/Mutex.cpp +common/thread/PeriodicThread.cpp +common/thread/SignalThread.cpp +common/thread/Thread.cpp +common/thread/ThreadPool.cpp +common/thread/ThreadPoolTest.cpp +common/thread/ThreadTest.cpp +common/thread/Utils.cpp +common/timecode/TimeCode.cpp +common/timecode/TimeCodeTest.cpp +common/utils/ActionQueue.cpp +common/utils/ActionQueueTest.cpp +common/utils/BackoffTest.cpp +common/utils/CallbackTest.cpp +common/utils/Clock.cpp +common/utils/ClockTest.cpp +common/utils/DmxBuffer.cpp +common/utils/DmxBufferTest.cpp +common/utils/MultiCallbackTest.cpp +common/utils/StringUtils.cpp +common/utils/StringUtilsTest.cpp +common/utils/TokenBucket.cpp +common/utils/TokenBucketTest.cpp +common/utils/UtilsTest.cpp +common/utils/Watchdog.cpp +common/utils/WatchdogTest.cpp +common/web/Json.cpp +common/web/JsonData.cpp +common/web/JsonLexer.cpp +common/web/JsonParser.cpp +common/web/JsonPatch.cpp +common/web/JsonPatchParser.cpp +common/web/JsonPointer.cpp +common/web/JsonSchema.cpp +common/web/JsonSections.cpp +common/web/JsonTest.cpp +common/web/JsonTypes.cpp +common/web/JsonWriter.cpp +common/web/ParserTest.cpp +common/web/PatchParserTest.cpp +common/web/PatchTest.cpp +common/web/PointerTest.cpp +common/web/PointerTracker.cpp +common/web/PointerTracker.h +common/web/PointerTrackerTest.cpp +common/web/SchemaErrorLogger.cpp +common/web/SchemaErrorLogger.h +common/web/SchemaKeywords.cpp +common/web/SchemaKeywords.h +common/web/SchemaParseContext.cpp +common/web/SchemaParseContext.h +common/web/SchemaParser.cpp +common/web/SchemaParser.h +common/web/SchemaParserTest.cpp +common/web/SchemaTest.cpp +common/web/SectionsTest.cpp +config.h +data/rdm/PidDataTest.cpp +doxygen/examples/callback_client_transmit.cpp +doxygen/examples/client_disconnect.cpp +doxygen/examples/client_thread.cpp +doxygen/examples/fetch_plugins.cpp +doxygen/examples/flags.cpp +doxygen/examples/legacy_callback_client_transmit.cpp +doxygen/examples/legacy_receiver.cpp +doxygen/examples/legacy_streaming_client.cpp +doxygen/examples/receiver.cpp +doxygen/examples/stdin_handler.cpp +doxygen/examples/streaming_client.cpp +doxygen/examples/streaming_client_plugin.cpp +doxygen/examples/udp_server.cpp +examples/OlaConfigurator.cpp +examples/OlaConfigurator.h +examples/ShowLoader.cpp +examples/ShowLoader.h +examples/ShowPlayer.cpp +examples/ShowPlayer.h +examples/ShowRecorder.cpp +examples/ShowRecorder.h +examples/ShowSaver.cpp +examples/ShowSaver.h +examples/ola-artnet.cpp +examples/ola-client.cpp +examples/ola-dmxconsole.cpp +examples/ola-dmxmonitor.cpp +examples/ola-e131.cpp +examples/ola-latency.cpp +examples/ola-rdm-discover.cpp +examples/ola-rdm.cpp +examples/ola-recorder.cpp +examples/ola-streaming-client.cpp +examples/ola-throughput.cpp +examples/ola-timecode.cpp +examples/ola-uni-stats.cpp +examples/ola-usbpro.cpp +include/ola/ActionQueue.h +include/ola/BaseTypes.h +include/ola/Callback.h +include/ola/CallbackRunner.h +include/ola/Clock.h +include/ola/Constants.h +include/ola/DmxBuffer.h +include/ola/ExportMap.h +include/ola/Logging.h +include/ola/MultiCallback.h +include/ola/StringUtils.h +include/ola/acn/ACNPort.h +include/ola/acn/ACNVectors.h +include/ola/acn/CID.h +include/ola/base/Array.h +include/ola/base/Credentials.h +include/ola/base/Env.h +include/ola/base/Flags.h +include/ola/base/FlagsPrivate.h +include/ola/base/Init.h +include/ola/base/Macro.h +include/ola/base/SysExits.h +include/ola/base/Version.h +include/ola/client/CallbackTypes.h +include/ola/client/ClientArgs.h +include/ola/client/ClientRDMAPIShim.h +include/ola/client/ClientTypes.h +include/ola/client/ClientWrapper.h +include/ola/client/Module.h +include/ola/client/OlaClient.h +include/ola/client/Result.h +include/ola/client/StreamingClient.h +include/ola/dmx/RunLengthEncoder.h +include/ola/dmx/SourcePriorities.h +include/ola/e133/DeviceManager.h +include/ola/e133/E133Enums.h +include/ola/e133/E133Receiver.h +include/ola/e133/E133StatusHelper.h +include/ola/e133/E133URLParser.h +include/ola/e133/MessageBuilder.h +include/ola/file/Util.h +include/ola/http/HTTPServer.h +include/ola/http/OlaHTTPServer.h +include/ola/io/BigEndianStream.h +include/ola/io/ByteString.h +include/ola/io/Descriptor.h +include/ola/io/ExtendedSerial.h +include/ola/io/IOQueue.h +include/ola/io/IOStack.h +include/ola/io/IOUtils.h +include/ola/io/IOVecInterface.h +include/ola/io/InputBuffer.h +include/ola/io/InputStream.h +include/ola/io/MemoryBlock.h +include/ola/io/MemoryBlockPool.h +include/ola/io/MemoryBuffer.h +include/ola/io/NonBlockingSender.h +include/ola/io/OutputBuffer.h +include/ola/io/OutputStream.h +include/ola/io/SelectServer.h +include/ola/io/SelectServerInterface.h +include/ola/io/Serial.h +include/ola/io/StdinHandler.h +include/ola/math/Random.h +include/ola/messaging/Descriptor.h +include/ola/messaging/DescriptorVisitor.h +include/ola/messaging/Message.h +include/ola/messaging/MessagePrinter.h +include/ola/messaging/MessageVisitor.h +include/ola/messaging/SchemaPrinter.h +include/ola/messaging/StringMessageBuilder.h +include/ola/network/AdvancedTCPConnector.h +include/ola/network/HealthCheckedConnection.h +include/ola/network/IPV4Address.h +include/ola/network/Interface.h +include/ola/network/InterfacePicker.h +include/ola/network/MACAddress.h +include/ola/network/NetworkUtils.h +include/ola/network/Socket.h +include/ola/network/SocketAddress.h +include/ola/network/SocketCloser.h +include/ola/network/TCPConnector.h +include/ola/network/TCPSocket.h +include/ola/network/TCPSocketFactory.h +include/ola/plugin_id.h +include/ola/rdm/AckTimerResponder.h +include/ola/rdm/AdvancedDimmerResponder.h +include/ola/rdm/CommandPrinter.h +include/ola/rdm/DimmerResponder.h +include/ola/rdm/DimmerRootDevice.h +include/ola/rdm/DimmerSubDevice.h +include/ola/rdm/DiscoveryAgent.h +include/ola/rdm/DummyResponder.h +include/ola/rdm/MessageDeserializer.h +include/ola/rdm/MessageSerializer.h +include/ola/rdm/MovingLightResponder.h +include/ola/rdm/NetworkManagerInterface.h +include/ola/rdm/NetworkResponder.h +include/ola/rdm/OpenLightingEnums.h +include/ola/rdm/PidStore.h +include/ola/rdm/PidStoreHelper.h +include/ola/rdm/QueueingRDMController.h +include/ola/rdm/RDMAPI.h +include/ola/rdm/RDMAPIImplInterface.h +include/ola/rdm/RDMCommand.h +include/ola/rdm/RDMCommandSerializer.h +include/ola/rdm/RDMControllerAdaptor.h +include/ola/rdm/RDMControllerInterface.h +include/ola/rdm/RDMEnums.h +include/ola/rdm/RDMFrame.h +include/ola/rdm/RDMHelper.h +include/ola/rdm/RDMMessagePrinters.h +include/ola/rdm/RDMPacket.h +include/ola/rdm/RDMReply.h +include/ola/rdm/RDMResponseCodes.h +include/ola/rdm/ResponderHelper.h +include/ola/rdm/ResponderLoadSensor.h +include/ola/rdm/ResponderOps.h +include/ola/rdm/ResponderOpsPrivate.h +include/ola/rdm/ResponderPersonality.h +include/ola/rdm/ResponderSensor.h +include/ola/rdm/ResponderSettings.h +include/ola/rdm/ResponderSlotData.h +include/ola/rdm/SensorResponder.h +include/ola/rdm/StringMessageBuilder.h +include/ola/rdm/SubDeviceDispatcher.h +include/ola/rdm/UID.h +include/ola/rdm/UIDAllocator.h +include/ola/rdm/UIDSet.h +include/ola/rpc/RpcSessionHandler.h +include/ola/stl/STLUtils.h +include/ola/strings/Format.h +include/ola/strings/FormatPrivate.h +include/ola/strings/Utils.h +include/ola/system/Limits.h +include/ola/system/SystemUtils.h +include/ola/testing/MockUDPSocket.h +include/ola/testing/TestUtils.h +include/ola/thread/CallbackThread.h +include/ola/thread/ConsumerThread.h +include/ola/thread/ExecutorInterface.h +include/ola/thread/ExecutorThread.h +include/ola/thread/Future.h +include/ola/thread/FuturePrivate.h +include/ola/thread/Mutex.h +include/ola/thread/PeriodicThread.h +include/ola/thread/SchedulerInterface.h +include/ola/thread/SchedulingExecutorInterface.h +include/ola/thread/SignalThread.h +include/ola/thread/Thread.h +include/ola/thread/ThreadPool.h +include/ola/thread/Utils.h +include/ola/timecode/TimeCode.h +include/ola/timecode/TimeCodeEnums.h +include/ola/util/Backoff.h +include/ola/util/Deleter.h +include/ola/util/SequenceNumber.h +include/ola/util/Utils.h +include/ola/util/Watchdog.h +include/ola/web/Json.h +include/ola/web/JsonData.h +include/ola/web/JsonLexer.h +include/ola/web/JsonParser.h +include/ola/web/JsonPatch.h +include/ola/web/JsonPatchParser.h +include/ola/web/JsonPointer.h +include/ola/web/JsonSchema.h +include/ola/web/JsonSections.h +include/ola/web/JsonTypes.h +include/ola/web/JsonWriter.h +include/ola/web/OptionalItem.h +include/ola/win/CleanWinSock2.h +include/ola/win/CleanWindows.h +include/olad/Device.h +include/olad/DmxSource.h +include/olad/Plugin.h +include/olad/PluginAdaptor.h +include/olad/Port.h +include/olad/PortBroker.h +include/olad/PortConstants.h +include/olad/Preferences.h +include/olad/TokenBucket.h +include/olad/Universe.h +libs/acn/BaseInflator.cpp +libs/acn/BaseInflator.h +libs/acn/BaseInflatorTest.cpp +libs/acn/CID.cpp +libs/acn/CIDImpl.cpp +libs/acn/CIDImpl.h +libs/acn/CIDTest.cpp +libs/acn/DMPAddress.cpp +libs/acn/DMPAddress.h +libs/acn/DMPAddressTest.cpp +libs/acn/DMPE131Inflator.cpp +libs/acn/DMPE131Inflator.h +libs/acn/DMPHeader.h +libs/acn/DMPInflator.cpp +libs/acn/DMPInflator.h +libs/acn/DMPInflatorTest.cpp +libs/acn/DMPPDU.cpp +libs/acn/DMPPDU.h +libs/acn/DMPPDUTest.cpp +libs/acn/E131DiscoveryInflator.cpp +libs/acn/E131DiscoveryInflator.h +libs/acn/E131Header.h +libs/acn/E131Inflator.cpp +libs/acn/E131Inflator.h +libs/acn/E131InflatorTest.cpp +libs/acn/E131Node.cpp +libs/acn/E131Node.h +libs/acn/E131PDU.cpp +libs/acn/E131PDU.h +libs/acn/E131PDUTest.cpp +libs/acn/E131Sender.cpp +libs/acn/E131Sender.h +libs/acn/E131TestFramework.cpp +libs/acn/E131TestFramework.h +libs/acn/E133Header.h +libs/acn/E133Inflator.cpp +libs/acn/E133Inflator.h +libs/acn/E133InflatorTest.cpp +libs/acn/E133PDU.cpp +libs/acn/E133PDU.h +libs/acn/E133PDUTest.cpp +libs/acn/E133StatusInflator.cpp +libs/acn/E133StatusInflator.h +libs/acn/E133StatusPDU.cpp +libs/acn/E133StatusPDU.h +libs/acn/HeaderSet.h +libs/acn/HeaderSetTest.cpp +libs/acn/PDU.cpp +libs/acn/PDU.h +libs/acn/PDUTest.cpp +libs/acn/PDUTestCommon.h +libs/acn/PreamblePacker.cpp +libs/acn/PreamblePacker.h +libs/acn/RDMInflator.cpp +libs/acn/RDMInflator.h +libs/acn/RDMPDU.cpp +libs/acn/RDMPDU.h +libs/acn/RDMPDUTest.cpp +libs/acn/RootHeader.h +libs/acn/RootInflator.cpp +libs/acn/RootInflator.h +libs/acn/RootInflatorTest.cpp +libs/acn/RootPDU.cpp +libs/acn/RootPDU.h +libs/acn/RootPDUTest.cpp +libs/acn/RootSender.cpp +libs/acn/RootSender.h +libs/acn/RootSenderTest.cpp +libs/acn/TCPTransport.cpp +libs/acn/TCPTransport.h +libs/acn/TCPTransportTest.cpp +libs/acn/Transport.h +libs/acn/TransportHeader.h +libs/acn/UDPTransport.cpp +libs/acn/UDPTransport.h +libs/acn/UDPTransportTest.cpp +libs/acn/e131_loadtest.cpp +libs/acn/e131_transmit_test.cpp +libs/usb/HotplugAgent.cpp +libs/usb/HotplugAgent.h +libs/usb/JaRuleConstants.cpp +libs/usb/JaRuleConstants.h +libs/usb/JaRulePortHandle.cpp +libs/usb/JaRulePortHandle.h +libs/usb/JaRulePortHandleImpl.cpp +libs/usb/JaRulePortHandleImpl.h +libs/usb/JaRuleWidget.cpp +libs/usb/JaRuleWidget.h +libs/usb/JaRuleWidgetPort.cpp +libs/usb/JaRuleWidgetPort.h +libs/usb/LibUsbAdaptor.cpp +libs/usb/LibUsbAdaptor.h +libs/usb/LibUsbThread.cpp +libs/usb/LibUsbThread.h +libs/usb/LibUsbThreadTest.cpp +libs/usb/Types.cpp +libs/usb/Types.h +ola/AutoStart.cpp +ola/AutoStart.h +ola/ClientRDMAPIShim.cpp +ola/ClientTypesFactory.cpp +ola/ClientTypesFactory.h +ola/Module.cpp +ola/OlaCallbackClient.cpp +ola/OlaCallbackClient.h +ola/OlaClient.cpp +ola/OlaClientCore.cpp +ola/OlaClientCore.h +ola/OlaClientWrapper.cpp +ola/OlaClientWrapper.h +ola/OlaClientWrapperTest.cpp +ola/OlaDevice.h +ola/StreamingClient.cpp +ola/StreamingClient.h +ola/StreamingClientTest.cpp +olad/AvahiDiscoveryAgent.cpp +olad/AvahiDiscoveryAgent.h +olad/BonjourDiscoveryAgent.cpp +olad/BonjourDiscoveryAgent.h +olad/ClientBroker.cpp +olad/ClientBroker.h +olad/DiscoveryAgent.cpp +olad/DiscoveryAgent.h +olad/DynamicPluginLoader.cpp +olad/DynamicPluginLoader.h +olad/HttpServerActions.cpp +olad/HttpServerActions.h +olad/OlaDaemon.cpp +olad/OlaDaemon.h +olad/OlaServer.cpp +olad/OlaServer.h +olad/OlaServerServiceImpl.cpp +olad/OlaServerServiceImpl.h +olad/OlaServerServiceImplTest.cpp +olad/Olad.cpp +olad/OladHTTPServer.cpp +olad/OladHTTPServer.h +olad/PluginLoader.h +olad/PluginManager.cpp +olad/PluginManager.h +olad/PluginManagerTest.cpp +olad/RDMHTTPModule.cpp +olad/RDMHTTPModule.h +olad/plugin_api/Client.cpp +olad/plugin_api/Client.h +olad/plugin_api/ClientTest.cpp +olad/plugin_api/Device.cpp +olad/plugin_api/DeviceManager.cpp +olad/plugin_api/DeviceManager.h +olad/plugin_api/DeviceManagerTest.cpp +olad/plugin_api/DeviceTest.cpp +olad/plugin_api/DmxSource.cpp +olad/plugin_api/DmxSourceTest.cpp +olad/plugin_api/Plugin.cpp +olad/plugin_api/PluginAdaptor.cpp +olad/plugin_api/Port.cpp +olad/plugin_api/PortBroker.cpp +olad/plugin_api/PortManager.cpp +olad/plugin_api/PortManager.h +olad/plugin_api/PortManagerTest.cpp +olad/plugin_api/PortTest.cpp +olad/plugin_api/Preferences.cpp +olad/plugin_api/PreferencesTest.cpp +olad/plugin_api/TestCommon.h +olad/plugin_api/Universe.cpp +olad/plugin_api/UniverseStore.cpp +olad/plugin_api/UniverseStore.h +olad/plugin_api/UniverseTest.cpp +plugins/artnet/ArtNetDevice.cpp +plugins/artnet/ArtNetDevice.h +plugins/artnet/ArtNetNode.cpp +plugins/artnet/ArtNetNode.h +plugins/artnet/ArtNetNodeTest.cpp +plugins/artnet/ArtNetPackets.h +plugins/artnet/ArtNetPlugin.cpp +plugins/artnet/ArtNetPlugin.h +plugins/artnet/ArtNetPluginDescription.h +plugins/artnet/ArtNetPort.cpp +plugins/artnet/ArtNetPort.h +plugins/artnet/artnet_loadtest.cpp +plugins/artnet/messages/ArtNetConfigMessages.pb.cc +plugins/artnet/messages/ArtNetConfigMessages.pb.h +plugins/dmx4linux/Dmx4LinuxDevice.cpp +plugins/dmx4linux/Dmx4LinuxDevice.h +plugins/dmx4linux/Dmx4LinuxPlugin.cpp +plugins/dmx4linux/Dmx4LinuxPlugin.h +plugins/dmx4linux/Dmx4LinuxPort.cpp +plugins/dmx4linux/Dmx4LinuxPort.h +plugins/dmx4linux/Dmx4LinuxSocket.h +plugins/dummy/DummyDevice.cpp +plugins/dummy/DummyDevice.h +plugins/dummy/DummyPlugin.cpp +plugins/dummy/DummyPlugin.h +plugins/dummy/DummyPluginDescription.h +plugins/dummy/DummyPort.cpp +plugins/dummy/DummyPort.h +plugins/dummy/DummyPortTest.cpp +plugins/e131/E131Device.cpp +plugins/e131/E131Device.h +plugins/e131/E131Plugin.cpp +plugins/e131/E131Plugin.h +plugins/e131/E131PluginDescription.h +plugins/e131/E131Port.cpp +plugins/e131/E131Port.h +plugins/e131/messages/E131ConfigMessages.pb.cc +plugins/e131/messages/E131ConfigMessages.pb.h +plugins/espnet/EspNetDevice.cpp +plugins/espnet/EspNetDevice.h +plugins/espnet/EspNetNode.cpp +plugins/espnet/EspNetNode.h +plugins/espnet/EspNetPackets.h +plugins/espnet/EspNetPlugin.cpp +plugins/espnet/EspNetPlugin.h +plugins/espnet/EspNetPluginCommon.h +plugins/espnet/EspNetPluginDescription.h +plugins/espnet/EspNetPort.cpp +plugins/espnet/EspNetPort.h +plugins/espnet/RunLengthDecoder.cpp +plugins/espnet/RunLengthDecoder.h +plugins/espnet/RunLengthDecoderTest.cpp +plugins/ftdidmx/FtdiDmxDevice.cpp +plugins/ftdidmx/FtdiDmxDevice.h +plugins/ftdidmx/FtdiDmxPlugin.cpp +plugins/ftdidmx/FtdiDmxPlugin.h +plugins/ftdidmx/FtdiDmxPluginDescription.h +plugins/ftdidmx/FtdiDmxPort.h +plugins/ftdidmx/FtdiDmxThread.cpp +plugins/ftdidmx/FtdiDmxThread.h +plugins/ftdidmx/FtdiWidget.cpp +plugins/ftdidmx/FtdiWidget.h +plugins/gpio/GPIODevice.cpp +plugins/gpio/GPIODevice.h +plugins/gpio/GPIODriver.cpp +plugins/gpio/GPIODriver.h +plugins/gpio/GPIOPlugin.cpp +plugins/gpio/GPIOPlugin.h +plugins/gpio/GPIOPluginDescription.h +plugins/gpio/GPIOPort.cpp +plugins/gpio/GPIOPort.h +plugins/karate/KarateDevice.cpp +plugins/karate/KarateDevice.h +plugins/karate/KarateLight.cpp +plugins/karate/KarateLight.h +plugins/karate/KaratePlugin.cpp +plugins/karate/KaratePlugin.h +plugins/karate/KaratePluginDescription.h +plugins/karate/KaratePort.h +plugins/karate/KarateThread.cpp +plugins/karate/KarateThread.h +plugins/kinet/KiNetDevice.cpp +plugins/kinet/KiNetDevice.h +plugins/kinet/KiNetNode.cpp +plugins/kinet/KiNetNode.h +plugins/kinet/KiNetNodeTest.cpp +plugins/kinet/KiNetPlugin.cpp +plugins/kinet/KiNetPlugin.h +plugins/kinet/KiNetPluginDescription.h +plugins/kinet/KiNetPort.h +plugins/kinet/kinet.cpp +plugins/milinst/MilInstDevice.cpp +plugins/milinst/MilInstDevice.h +plugins/milinst/MilInstPlugin.cpp +plugins/milinst/MilInstPlugin.h +plugins/milinst/MilInstPluginDescription.h +plugins/milinst/MilInstPort.cpp +plugins/milinst/MilInstPort.h +plugins/milinst/MilInstWidget.cpp +plugins/milinst/MilInstWidget.h +plugins/milinst/MilInstWidget1463.cpp +plugins/milinst/MilInstWidget1463.h +plugins/milinst/MilInstWidget1553.cpp +plugins/milinst/MilInstWidget1553.h +plugins/nanoleaf/NanoleafDevice.cpp +plugins/nanoleaf/NanoleafDevice.h +plugins/nanoleaf/NanoleafNode.cpp +plugins/nanoleaf/NanoleafNode.h +plugins/nanoleaf/NanoleafNodeTest.cpp +plugins/nanoleaf/NanoleafPlugin.cpp +plugins/nanoleaf/NanoleafPlugin.h +plugins/nanoleaf/NanoleafPluginDescription.h +plugins/nanoleaf/NanoleafPort.h +plugins/opendmx/OpenDmxDevice.cpp +plugins/opendmx/OpenDmxDevice.h +plugins/opendmx/OpenDmxPlugin.cpp +plugins/opendmx/OpenDmxPlugin.h +plugins/opendmx/OpenDmxPluginDescription.h +plugins/opendmx/OpenDmxPort.h +plugins/opendmx/OpenDmxThread.cpp +plugins/opendmx/OpenDmxThread.h +plugins/openpixelcontrol/OPCClient.cpp +plugins/openpixelcontrol/OPCClient.h +plugins/openpixelcontrol/OPCClientTest.cpp +plugins/openpixelcontrol/OPCConstants.h +plugins/openpixelcontrol/OPCDevice.cpp +plugins/openpixelcontrol/OPCDevice.h +plugins/openpixelcontrol/OPCPlugin.cpp +plugins/openpixelcontrol/OPCPlugin.h +plugins/openpixelcontrol/OPCPluginDescription.h +plugins/openpixelcontrol/OPCPort.cpp +plugins/openpixelcontrol/OPCPort.h +plugins/openpixelcontrol/OPCServer.cpp +plugins/openpixelcontrol/OPCServer.h +plugins/openpixelcontrol/OPCServerTest.cpp +plugins/osc/OSCAddressTemplate.cpp +plugins/osc/OSCAddressTemplate.h +plugins/osc/OSCAddressTemplateTest.cpp +plugins/osc/OSCDevice.cpp +plugins/osc/OSCDevice.h +plugins/osc/OSCNode.cpp +plugins/osc/OSCNode.h +plugins/osc/OSCNodeTest.cpp +plugins/osc/OSCPlugin.cpp +plugins/osc/OSCPlugin.h +plugins/osc/OSCPort.cpp +plugins/osc/OSCPort.h +plugins/osc/OSCTarget.h +plugins/pathport/PathportDevice.cpp +plugins/pathport/PathportDevice.h +plugins/pathport/PathportNode.cpp +plugins/pathport/PathportNode.h +plugins/pathport/PathportPackets.h +plugins/pathport/PathportPlugin.cpp +plugins/pathport/PathportPlugin.h +plugins/pathport/PathportPluginDescription.h +plugins/pathport/PathportPort.cpp +plugins/pathport/PathportPort.h +plugins/renard/RenardDevice.cpp +plugins/renard/RenardDevice.h +plugins/renard/RenardPlugin.cpp +plugins/renard/RenardPlugin.h +plugins/renard/RenardPluginDescription.h +plugins/renard/RenardPort.cpp +plugins/renard/RenardPort.h +plugins/renard/RenardWidget.cpp +plugins/renard/RenardWidget.h +plugins/sandnet/SandNetCommon.h +plugins/sandnet/SandNetDevice.cpp +plugins/sandnet/SandNetDevice.h +plugins/sandnet/SandNetNode.cpp +plugins/sandnet/SandNetNode.h +plugins/sandnet/SandNetPackets.h +plugins/sandnet/SandNetPlugin.cpp +plugins/sandnet/SandNetPlugin.h +plugins/sandnet/SandNetPluginDescription.h +plugins/sandnet/SandNetPort.cpp +plugins/sandnet/SandNetPort.h +plugins/shownet/ShowNetDevice.cpp +plugins/shownet/ShowNetDevice.h +plugins/shownet/ShowNetNode.cpp +plugins/shownet/ShowNetNode.h +plugins/shownet/ShowNetNodeTest.cpp +plugins/shownet/ShowNetPackets.h +plugins/shownet/ShowNetPlugin.cpp +plugins/shownet/ShowNetPlugin.h +plugins/shownet/ShowNetPluginDescription.h +plugins/shownet/ShowNetPort.cpp +plugins/shownet/ShowNetPort.h +plugins/spi/FakeSPIWriter.cpp +plugins/spi/FakeSPIWriter.h +plugins/spi/SPIBackend.cpp +plugins/spi/SPIBackend.h +plugins/spi/SPIBackendTest.cpp +plugins/spi/SPIDevice.cpp +plugins/spi/SPIDevice.h +plugins/spi/SPIOutput.cpp +plugins/spi/SPIOutput.h +plugins/spi/SPIOutputTest.cpp +plugins/spi/SPIPlugin.cpp +plugins/spi/SPIPlugin.h +plugins/spi/SPIPluginDescription.h +plugins/spi/SPIPort.cpp +plugins/spi/SPIPort.h +plugins/spi/SPIWriter.cpp +plugins/spi/SPIWriter.h +plugins/spidmx/SPIDMXDevice.cpp +plugins/spidmx/SPIDMXDevice.h +plugins/spidmx/SPIDMXParser.cpp +plugins/spidmx/SPIDMXParser.h +plugins/spidmx/SPIDMXPlugin.cpp +plugins/spidmx/SPIDMXPlugin.h +plugins/spidmx/SPIDMXPluginDescription.h +plugins/spidmx/SPIDMXPort.h +plugins/spidmx/SPIDMXThread.cpp +plugins/spidmx/SPIDMXThread.h +plugins/spidmx/SPIDMXWidget.cpp +plugins/spidmx/SPIDMXWidget.h +plugins/stageprofi/StageProfiDetector.cpp +plugins/stageprofi/StageProfiDetector.h +plugins/stageprofi/StageProfiDevice.cpp +plugins/stageprofi/StageProfiDevice.h +plugins/stageprofi/StageProfiPlugin.cpp +plugins/stageprofi/StageProfiPlugin.h +plugins/stageprofi/StageProfiPluginDescription.h +plugins/stageprofi/StageProfiPort.cpp +plugins/stageprofi/StageProfiPort.h +plugins/stageprofi/StageProfiWidget.cpp +plugins/stageprofi/StageProfiWidget.h +plugins/uartdmx/UartDmxDevice.cpp +plugins/uartdmx/UartDmxDevice.h +plugins/uartdmx/UartDmxPlugin.cpp +plugins/uartdmx/UartDmxPlugin.h +plugins/uartdmx/UartDmxPluginDescription.h +plugins/uartdmx/UartDmxPort.h +plugins/uartdmx/UartDmxThread.cpp +plugins/uartdmx/UartDmxThread.h +plugins/uartdmx/UartWidget.cpp +plugins/uartdmx/UartWidget.h +plugins/usbdmx/AVLdiyD512.cpp +plugins/usbdmx/AVLdiyD512.h +plugins/usbdmx/AVLdiyD512Factory.cpp +plugins/usbdmx/AVLdiyD512Factory.h +plugins/usbdmx/AnymauDMX.cpp +plugins/usbdmx/AnymauDMX.h +plugins/usbdmx/AnymauDMXFactory.cpp +plugins/usbdmx/AnymauDMXFactory.h +plugins/usbdmx/AsyncPluginImpl.cpp +plugins/usbdmx/AsyncPluginImpl.h +plugins/usbdmx/AsyncUsbReceiver.cpp +plugins/usbdmx/AsyncUsbReceiver.h +plugins/usbdmx/AsyncUsbSender.cpp +plugins/usbdmx/AsyncUsbSender.h +plugins/usbdmx/AsyncUsbTransceiverBase.cpp +plugins/usbdmx/AsyncUsbTransceiverBase.h +plugins/usbdmx/DMXCProjectsNodleU1.cpp +plugins/usbdmx/DMXCProjectsNodleU1.h +plugins/usbdmx/DMXCProjectsNodleU1Device.cpp +plugins/usbdmx/DMXCProjectsNodleU1Device.h +plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp +plugins/usbdmx/DMXCProjectsNodleU1Factory.h +plugins/usbdmx/DMXCProjectsNodleU1Port.cpp +plugins/usbdmx/DMXCProjectsNodleU1Port.h +plugins/usbdmx/DMXCreator512Basic.cpp +plugins/usbdmx/DMXCreator512Basic.h +plugins/usbdmx/DMXCreator512BasicFactory.cpp +plugins/usbdmx/DMXCreator512BasicFactory.h +plugins/usbdmx/EurolitePro.cpp +plugins/usbdmx/EurolitePro.h +plugins/usbdmx/EuroliteProFactory.cpp +plugins/usbdmx/EuroliteProFactory.h +plugins/usbdmx/FirmwareLoader.h +plugins/usbdmx/Flags.cpp +plugins/usbdmx/GenericDevice.cpp +plugins/usbdmx/GenericDevice.h +plugins/usbdmx/GenericOutputPort.cpp +plugins/usbdmx/GenericOutputPort.h +plugins/usbdmx/JaRuleDevice.cpp +plugins/usbdmx/JaRuleDevice.h +plugins/usbdmx/JaRuleFactory.cpp +plugins/usbdmx/JaRuleFactory.h +plugins/usbdmx/JaRuleOutputPort.cpp +plugins/usbdmx/JaRuleOutputPort.h +plugins/usbdmx/PluginImplInterface.h +plugins/usbdmx/ScanlimeFadecandy.cpp +plugins/usbdmx/ScanlimeFadecandy.h +plugins/usbdmx/ScanlimeFadecandyFactory.cpp +plugins/usbdmx/ScanlimeFadecandyFactory.h +plugins/usbdmx/ShowJockeyDMXU1.cpp +plugins/usbdmx/ShowJockeyDMXU1.h +plugins/usbdmx/ShowJockeyDMXU1Factory.cpp +plugins/usbdmx/ShowJockeyDMXU1Factory.h +plugins/usbdmx/Sunlite.cpp +plugins/usbdmx/Sunlite.h +plugins/usbdmx/SunliteFactory.cpp +plugins/usbdmx/SunliteFactory.h +plugins/usbdmx/SunliteFirmware.h +plugins/usbdmx/SunliteFirmwareLoader.cpp +plugins/usbdmx/SunliteFirmwareLoader.h +plugins/usbdmx/SyncPluginImpl.cpp +plugins/usbdmx/SyncPluginImpl.h +plugins/usbdmx/SynchronizedWidgetObserver.cpp +plugins/usbdmx/SynchronizedWidgetObserver.h +plugins/usbdmx/ThreadedUsbReceiver.cpp +plugins/usbdmx/ThreadedUsbReceiver.h +plugins/usbdmx/ThreadedUsbSender.cpp +plugins/usbdmx/ThreadedUsbSender.h +plugins/usbdmx/UsbDmxPlugin.cpp +plugins/usbdmx/UsbDmxPlugin.h +plugins/usbdmx/UsbDmxPluginDescription.h +plugins/usbdmx/VellemanK8062.cpp +plugins/usbdmx/VellemanK8062.h +plugins/usbdmx/VellemanK8062Factory.cpp +plugins/usbdmx/VellemanK8062Factory.h +plugins/usbdmx/Widget.h +plugins/usbdmx/WidgetFactory.h +plugins/usbpro/ArduinoRGBDevice.cpp +plugins/usbpro/ArduinoRGBDevice.h +plugins/usbpro/ArduinoWidget.cpp +plugins/usbpro/ArduinoWidget.h +plugins/usbpro/ArduinoWidgetTest.cpp +plugins/usbpro/BaseRobeWidget.cpp +plugins/usbpro/BaseRobeWidget.h +plugins/usbpro/BaseRobeWidgetTest.cpp +plugins/usbpro/BaseUsbProWidget.cpp +plugins/usbpro/BaseUsbProWidget.h +plugins/usbpro/BaseUsbProWidgetTest.cpp +plugins/usbpro/CommonWidgetTest.cpp +plugins/usbpro/CommonWidgetTest.h +plugins/usbpro/DmxTriDevice.cpp +plugins/usbpro/DmxTriDevice.h +plugins/usbpro/DmxTriWidget.cpp +plugins/usbpro/DmxTriWidget.h +plugins/usbpro/DmxTriWidgetTest.cpp +plugins/usbpro/DmxterDevice.cpp +plugins/usbpro/DmxterDevice.h +plugins/usbpro/DmxterWidget.cpp +plugins/usbpro/DmxterWidget.h +plugins/usbpro/DmxterWidgetTest.cpp +plugins/usbpro/EnttecUsbProWidget.cpp +plugins/usbpro/EnttecUsbProWidget.h +plugins/usbpro/EnttecUsbProWidgetImpl.h +plugins/usbpro/EnttecUsbProWidgetTest.cpp +plugins/usbpro/GenericUsbProWidget.cpp +plugins/usbpro/GenericUsbProWidget.h +plugins/usbpro/MockEndpoint.cpp +plugins/usbpro/MockEndpoint.h +plugins/usbpro/RobeDevice.cpp +plugins/usbpro/RobeDevice.h +plugins/usbpro/RobeWidget.cpp +plugins/usbpro/RobeWidget.h +plugins/usbpro/RobeWidgetDetector.cpp +plugins/usbpro/RobeWidgetDetector.h +plugins/usbpro/RobeWidgetDetectorTest.cpp +plugins/usbpro/RobeWidgetTest.cpp +plugins/usbpro/SerialWidgetInterface.h +plugins/usbpro/UltraDMXProDevice.cpp +plugins/usbpro/UltraDMXProDevice.h +plugins/usbpro/UltraDMXProWidget.cpp +plugins/usbpro/UltraDMXProWidget.h +plugins/usbpro/UltraDMXProWidgetTest.cpp +plugins/usbpro/UsbProDevice.cpp +plugins/usbpro/UsbProDevice.h +plugins/usbpro/UsbProWidgetDetector.cpp +plugins/usbpro/UsbProWidgetDetector.h +plugins/usbpro/UsbProWidgetDetectorTest.cpp +plugins/usbpro/UsbSerialDevice.h +plugins/usbpro/UsbSerialPlugin.cpp +plugins/usbpro/UsbSerialPlugin.h +plugins/usbpro/UsbSerialPluginDescription.h +plugins/usbpro/WidgetDetectorInterface.h +plugins/usbpro/WidgetDetectorThread.cpp +plugins/usbpro/WidgetDetectorThread.h +plugins/usbpro/WidgetDetectorThreadTest.cpp +plugins/usbpro/messages/UsbProConfigMessages.pb.cc +plugins/usbpro/messages/UsbProConfigMessages.pb.h +protoc/CppFileGenerator.cpp +protoc/CppFileGenerator.h +protoc/CppGenerator.cpp +protoc/CppGenerator.h +protoc/GeneratorHelpers.cpp +protoc/GeneratorHelpers.h +protoc/ServiceGenerator.cpp +protoc/ServiceGenerator.h +protoc/StrUtil.cpp +protoc/StrUtil.h +protoc/ola-protoc-generator-plugin.cpp +tools/e133/DesignatedControllerConnection.cpp +tools/e133/DesignatedControllerConnection.h +tools/e133/DeviceManager.cpp +tools/e133/DeviceManagerImpl.cpp +tools/e133/DeviceManagerImpl.h +tools/e133/E133Device.cpp +tools/e133/E133Device.h +tools/e133/E133Endpoint.cpp +tools/e133/E133Endpoint.h +tools/e133/E133HealthCheckedConnection.cpp +tools/e133/E133HealthCheckedConnection.h +tools/e133/E133Receiver.cpp +tools/e133/E133StatusHelper.cpp +tools/e133/EndpointManager.cpp +tools/e133/EndpointManager.h +tools/e133/ManagementEndpoint.cpp +tools/e133/ManagementEndpoint.h +tools/e133/MessageBuilder.cpp +tools/e133/SimpleE133Node.cpp +tools/e133/SimpleE133Node.h +tools/e133/TCPConnectionStats.h +tools/e133/basic-controller.cpp +tools/e133/basic-device.cpp +tools/e133/e133-controller.cpp +tools/e133/e133-monitor.cpp +tools/e133/e133-receiver.cpp +tools/ja-rule/USBDeviceManager.cpp +tools/ja-rule/USBDeviceManager.h +tools/ja-rule/ja-rule-controller.cpp +tools/ja-rule/ja-rule.cpp +tools/logic/DMXSignalProcessor.cpp +tools/logic/DMXSignalProcessor.h +tools/logic/logic-rdm-sniffer.cpp +tools/ola_trigger/Action.cpp +tools/ola_trigger/Action.h +tools/ola_trigger/ActionTest.cpp +tools/ola_trigger/ConfigCommon.h +tools/ola_trigger/Context.cpp +tools/ola_trigger/Context.h +tools/ola_trigger/ContextTest.cpp +tools/ola_trigger/DMXTrigger.cpp +tools/ola_trigger/DMXTrigger.h +tools/ola_trigger/DMXTriggerTest.cpp +tools/ola_trigger/IntervalTest.cpp +tools/ola_trigger/MockAction.h +tools/ola_trigger/ParserActions.cpp +tools/ola_trigger/ParserActions.h +tools/ola_trigger/ParserGlobals.h +tools/ola_trigger/SlotTest.cpp +tools/ola_trigger/VariableInterpolator.cpp +tools/ola_trigger/VariableInterpolator.h +tools/ola_trigger/VariableInterpolatorTest.cpp +tools/ola_trigger/config.tab.cpp +tools/ola_trigger/config.tab.h +tools/ola_trigger/lex.yy.cpp +tools/ola_trigger/ola-trigger.cpp +tools/rdmpro/rdm-sniffer.cpp +tools/usbpro/usbpro-firmware.cpp diff --git a/OLA.includes b/OLA.includes new file mode 100644 index 0000000000..71af031e80 --- /dev/null +++ b/OLA.includes @@ -0,0 +1,69 @@ +. +common/io +common/network +common/protocol +common/rdm +common/rpc +common/web +examples +include/ola +include/ola/acn +include/ola/base +include/ola/client +include/ola/dmx +include/ola/e133 +include/ola/file +include/ola/http +include/ola/io +include/ola/math +include/ola/messaging +include/ola/network +include/ola/rdm +include/ola/rpc +include/ola/stl +include/ola/strings +include/ola/system +include/ola/testing +include/ola/thread +include/ola/timecode +include/ola/util +include/ola/web +include/ola/win +include/olad +libs/acn +libs/usb +ola +olad +olad/plugin_api +plugins/artnet +plugins/artnet/messages +plugins/dmx4linux +plugins/dummy +plugins/e131 +plugins/e131/messages +plugins/espnet +plugins/ftdidmx +plugins/gpio +plugins/karate +plugins/kinet +plugins/milinst +plugins/nanoleaf +plugins/opendmx +plugins/openpixelcontrol +plugins/osc +plugins/pathport +plugins/renard +plugins/sandnet +plugins/shownet +plugins/spi +plugins/spidmx +plugins/stageprofi +plugins/uartdmx +plugins/usbdmx +plugins/usbpro +plugins/usbpro/messages +protoc +tools/e133 +tools/ja-rule +tools/logic +tools/ola_trigger diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 3328d13605..d7c7b5544a 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -53,13 +53,7 @@ class FtdiDmxOutputPort unsigned int freq) : BasicOutputPort(parent, id, false, true), m_interface(interface), - m_thread(interface, freq), - m_transaction_number(0), - m_discovery_agent(this), - m_uid(0x7a7012345678), - m_mute_complete(nullptr), - m_unmute_complete(nullptr), - m_branch_callback(nullptr) { + m_thread(interface, freq) { m_thread.Start(); } ~FtdiDmxOutputPort() { @@ -73,82 +67,30 @@ class FtdiDmxOutputPort void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { - request->SetTransactionNumber(m_transaction_number++); m_thread.SendRDMRequest(request, callback); } std::string Description() const { return m_interface->Description(); } - void on_mute_reply(RDMReply *mute_reply) { - MuteDeviceCallback *my_mute_complete = m_mute_complete; - m_mute_complete = nullptr; - //if(mute_reply->Response().SourceUID() == ) - my_mute_complete->Run(true); - } - - void on_unmute_complete(RDMReply *unmute_reply) { - UnMuteDeviceCallback *my_unmute_complete = m_unmute_complete; - m_unmute_complete = nullptr; - ola::rdm::rdm_response_code response = unmute_reply->StatusCode(); - if(response == rdm::RDM_WAS_BROADCAST || response == rdm::RDM_COMPLETED_OK) { - my_unmute_complete->Run(); - } else { - OLA_WARN << "Something went wrong broadcasting unmute"; - my_unmute_complete->Run(); - } - } - - void on_branch_callback(RDMReply *branch_reply) { - BranchCallback *my_branch_callback = m_branch_callback; - m_branch_callback = nullptr; - my_branch_callback->Run(branch_reply->frame().data, branch_reply->frame().length); - } - void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete){ - if(m_mute_complete == nullptr) { - m_mute_complete = mute_complete; - m_thread.SendRDMRequest(ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number++), - &on_mute_reply); - } else { - //fail - } + m_thread.MuteDevice(target, mute_complete); } + void UnMuteAll(UnMuteDeviceCallback *unmute_complete) { - if(m_unmute_complete == nullptr) { - m_unmute_complete = unmute_complete; - m_thread.SendRDMRequest(ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), - m_transaction_number++), - [&FtdiDmxOutputPort](RDMRequest*) { return on_unmute_complete(RDMReply *unmute_reply)) }; - } else { - //fail - } + m_thread.UnMuteAll(unmute_complete); } + void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { - if(m_branch_callback == nullptr) { - m_branch_callback = callback; - m_thread.SendRDMRequest(ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, - m_transaction_number++), - &on_branch_callback); - } else { - //fail - } + m_thread.Branch(lower, upper, callback); } private: FtdiInterface *m_interface; FtdiDmxThread m_thread; - uint8_t m_transaction_number; - ola::rdm::DiscoveryAgent m_discovery_agent; - const ola::rdm::UID m_uid; - - MuteDeviceCallback *m_mute_complete; - UnMuteDeviceCallback * m_unmute_complete; - BranchCallback * m_branch_callback; - }; } // namespace ftdidmx } // namespace plugin diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 80f6e6a768..ef0eb62f58 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -38,6 +38,7 @@ #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMResponseCodes.h" +#include "ola/rdm/DiscoveryAgent.h" #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" @@ -50,7 +51,13 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency) : m_granularity(UNKNOWN), m_interface(interface), m_term(false), - m_frequency(frequency) { + m_frequency(frequency), + m_transaction_number(0), + m_discovery_agent(this), + m_uid(0x7a70, 0x12345678), + m_mute_complete(nullptr), + m_unmute_complete(nullptr), + m_branch_callback(nullptr) { } FtdiDmxThread::~FtdiDmxThread() { @@ -87,9 +94,34 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { + request->SetTransactionNumber(m_transaction_number += 1); m_RDMQueue.push(std::pair(request, callback)); -}; +} + +void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, + MuteDeviceCallback *mute_complete) { + if(m_mute_complete == nullptr) { + m_mute_complete = mute_complete; + SendRDMRequest(ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1), nullptr); + } +} + +void FtdiDmxThread::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { + if(m_unmute_complete == nullptr){ + m_unmute_complete = unmute_complete; + SendRDMRequest(ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number += 1), nullptr); + } +} + +void FtdiDmxThread::Branch(const ola::rdm::UID &lower, + const ola::rdm::UID &upper, + BranchCallback *callback) { + if(m_branch_callback == nullptr) { + m_branch_callback = callback; + SendRDMRequest(ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1), nullptr); + } +} /** * @brief The method called by the thread @@ -104,6 +136,9 @@ void *FtdiDmxThread::Run() { int readBytes; unsigned char readBuffer[258]; ola::io::ByteString packetBuffer; + MuteDeviceCallback *thread_mute_callback = nullptr; + UnMuteDeviceCallback *thread_unmute_callback = nullptr; + BranchCallback *thread_branch_callback = nullptr; int frameTime = static_cast(floor( @@ -169,28 +204,66 @@ void *FtdiDmxThread::Run() { } else { if(m_interface->Write(&packetBuffer)) { if(m_RDMQueue.front().first->IsDUB()) { + thread_branch_callback = m_branch_callback; + m_branch_callback = nullptr; + usleep(1400); readBytes = m_interface->Read(readBuffer, 258); - if(readBytes <= 0) { // also catches hw issues, slightly incorrect, but they were already reported at hw layer. - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_TIMEOUT); + + // also catches hw issues, slightly incorrect, but they were already reported at hw layer. + if(readBytes < 0) { + //RunRDMCallback(thread_branch_callback, rdm::RDM_TIMEOUT); } else if (readBytes <= 24) {// Ignores potential for bad splitters dropping preamble bytes. - m_RDMQueue.front().second->Run(rdm::RDMReply::DUBReply(rdm::RDMFrame(readBuffer, readBytes))); + thread_branch_callback->Run(readBuffer, readBytes); + thread_branch_callback = nullptr; } else { // Invalid response (collision) } } else if(!m_RDMQueue.front().first->DestinationUID().IsBroadcast()) { - usleep(31000); // Wait half the time needed for broadcasting 512 bytes (full packet which is impossible in RDM) + // Wait half the time needed for broadcasting 512 bytes (full packet which is impossible in RDM) + usleep(31000); + readBytes = m_interface->Read(readBuffer, 258); - if(readBytes <= 0) { // also catches hw issues, slightly incorrect, but they were already reported at hw layer. + + // also catches hw issues, slightly incorrect, but they were already reported at hw layer. + if(readBytes <= 0) { RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_TIMEOUT); } else { - m_RDMQueue.front().second->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_RDMQueue.front().first)); + // The following block of code makes the assumption that only 1 callback pointer will be set at the same time, + // this assumption is patently false but we are hacking things to get an initial POC + if (m_RDMQueue.front().second != nullptr) { + m_RDMQueue.front().second->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_RDMQueue.front().first)); + } else if (m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_RDMQueue.front().first->DestinationUID()) { + thread_mute_callback->Run(true); + } else { + thread_mute_callback->Run(false); + } + thread_mute_callback = nullptr; + } } } else { - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_WAS_BROADCAST); + if (m_RDMQueue.front().second != nullptr) { + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_WAS_BROADCAST); + } else if(m_unmute_complete != nullptr) { + thread_unmute_callback = m_unmute_complete; + m_unmute_complete = nullptr; + thread_unmute_callback->Run(); + thread_unmute_callback = nullptr; + } } } else { - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); + if (m_RDMQueue.front().second != nullptr) { + RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); + } else if(m_branch_callback != nullptr) { + + } else if(m_mute_complete != nullptr) { + + } else if(m_unmute_complete != nullptr) { + + } } m_RDMQueue.pop(); goto framesleep; diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 3a55ad732e..d076c81db7 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -32,13 +32,16 @@ #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" #include "ola/rdm/RDMCommand.h" - +#include "ola/rdm/DiscoveryAgent.h" +#include "ola/rdm/RDMResponseCodes.h" namespace ola { namespace plugin { namespace ftdidmx { -class FtdiDmxThread : public ola::thread::Thread { +class FtdiDmxThread + : public ola::thread::Thread, + public ola::rdm::DiscoveryTargetInterface { public: FtdiDmxThread(FtdiInterface *interface, unsigned int frequency); ~FtdiDmxThread(); @@ -49,6 +52,16 @@ class FtdiDmxThread : public ola::thread::Thread { void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); + void MuteDevice(const ola::rdm::UID &target, + MuteDeviceCallback *mute_complete); + + void UnMuteAll(UnMuteDeviceCallback *unmute_complete); + + void Branch(const ola::rdm::UID &lower, + const ola::rdm::UID &upper, + BranchCallback *callback); + + private: enum TimerGranularity { UNKNOWN, GOOD, BAD }; @@ -61,6 +74,14 @@ class FtdiDmxThread : public ola::thread::Thread { ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; + uint8_t m_transaction_number; + ola::rdm::DiscoveryAgent m_discovery_agent; + const ola::rdm::UID m_uid; + + MuteDeviceCallback *m_mute_complete; + UnMuteDeviceCallback *m_unmute_complete; + BranchCallback *m_branch_callback; + std::queue> m_RDMQueue; From 10fc5a09e92ed5da513f4d20d8ee4a165d12a181 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 20 Dec 2018 00:45:51 +0200 Subject: [PATCH 06/86] Removed qtcreator files, added to .gitignore and added minor debug output to FtdiDmxThread::SendRDMRequest() --- .gitignore | 1 + OLA.config | 2 - OLA.creator | 1 - OLA.files | 1080 ----------------------------- OLA.includes | 69 -- plugins/ftdidmx/FtdiDmxThread.cpp | 1 + 6 files changed, 2 insertions(+), 1152 deletions(-) delete mode 100644 OLA.config delete mode 100644 OLA.creator delete mode 100644 OLA.files delete mode 100644 OLA.includes diff --git a/.gitignore b/.gitignore index ba14cfd698..17a3e1a58b 100644 --- a/.gitignore +++ b/.gitignore @@ -245,3 +245,4 @@ javascript/new-src/node_modules .cproject .settings .vscode/ +OLA.* diff --git a/OLA.config b/OLA.config deleted file mode 100644 index e0284f4257..0000000000 --- a/OLA.config +++ /dev/null @@ -1,2 +0,0 @@ -// Add predefined macros for your project here. For example: -// #define THE_ANSWER 42 diff --git a/OLA.creator b/OLA.creator deleted file mode 100644 index e94cbbd302..0000000000 --- a/OLA.creator +++ /dev/null @@ -1 +0,0 @@ -[General] diff --git a/OLA.files b/OLA.files deleted file mode 100644 index ead319fcc8..0000000000 --- a/OLA.files +++ /dev/null @@ -1,1080 +0,0 @@ -common/base/Credentials.cpp -common/base/CredentialsTest.cpp -common/base/Env.cpp -common/base/Flags.cpp -common/base/FlagsTest.cpp -common/base/Init.cpp -common/base/Logging.cpp -common/base/LoggingTest.cpp -common/base/SysExits.cpp -common/base/Version.cpp -common/dmx/RunLengthEncoder.cpp -common/dmx/RunLengthEncoderTest.cpp -common/export_map/ExportMap.cpp -common/export_map/ExportMapTest.cpp -common/file/Util.cpp -common/file/UtilTest.cpp -common/http/HTTPServer.cpp -common/http/OlaHTTPServer.cpp -common/io/Descriptor.cpp -common/io/DescriptorTest.cpp -common/io/EPoller.cpp -common/io/EPoller.h -common/io/ExtendedSerial.cpp -common/io/IOQueue.cpp -common/io/IOQueueTest.cpp -common/io/IOStack.cpp -common/io/IOStackTest.cpp -common/io/IOUtils.cpp -common/io/InputStreamTest.cpp -common/io/KQueuePoller.cpp -common/io/KQueuePoller.h -common/io/MemoryBlockTest.cpp -common/io/NonBlockingSender.cpp -common/io/OutputStreamTest.cpp -common/io/PollerInterface.cpp -common/io/PollerInterface.h -common/io/SelectPoller.cpp -common/io/SelectPoller.h -common/io/SelectServer.cpp -common/io/SelectServerTest.cpp -common/io/SelectServerThreadTest.cpp -common/io/Serial.cpp -common/io/StdinHandler.cpp -common/io/TimeoutManager.cpp -common/io/TimeoutManager.h -common/io/TimeoutManagerTest.cpp -common/io/WindowsPoller.cpp -common/io/WindowsPoller.h -common/math/Random.cpp -common/messaging/Descriptor.cpp -common/messaging/DescriptorTest.cpp -common/messaging/Message.cpp -common/messaging/MessagePrinter.cpp -common/messaging/MessagePrinterTest.cpp -common/messaging/SchemaPrinter.cpp -common/messaging/SchemaPrinterTest.cpp -common/network/AdvancedTCPConnector.cpp -common/network/AdvancedTCPConnectorTest.cpp -common/network/FakeInterfacePicker.h -common/network/HealthCheckedConnection.cpp -common/network/HealthCheckedConnectionTest.cpp -common/network/IPV4Address.cpp -common/network/IPV4AddressTest.cpp -common/network/Interface.cpp -common/network/InterfacePicker.cpp -common/network/InterfacePickerTest.cpp -common/network/InterfaceTest.cpp -common/network/MACAddress.cpp -common/network/MACAddressTest.cpp -common/network/NetworkUtils.cpp -common/network/NetworkUtilsInternal.h -common/network/NetworkUtilsTest.cpp -common/network/PosixInterfacePicker.cpp -common/network/PosixInterfacePicker.h -common/network/Socket.cpp -common/network/SocketAddress.cpp -common/network/SocketAddressTest.cpp -common/network/SocketCloser.cpp -common/network/SocketHelper.cpp -common/network/SocketHelper.h -common/network/SocketTest.cpp -common/network/TCPConnector.cpp -common/network/TCPConnectorTest.cpp -common/network/TCPSocket.cpp -common/network/WindowsInterfacePicker.cpp -common/network/WindowsInterfacePicker.h -common/protocol/Ola.pb.cc -common/protocol/Ola.pb.h -common/protocol/OlaService.pb.cpp -common/protocol/OlaService.pb.h -common/rdm/AckTimerResponder.cpp -common/rdm/AdvancedDimmerResponder.cpp -common/rdm/CommandPrinter.cpp -common/rdm/DescriptorConsistencyChecker.cpp -common/rdm/DescriptorConsistencyChecker.h -common/rdm/DescriptorConsistencyCheckerTest.cpp -common/rdm/DimmerResponder.cpp -common/rdm/DimmerRootDevice.cpp -common/rdm/DimmerSubDevice.cpp -common/rdm/DiscoveryAgent.cpp -common/rdm/DiscoveryAgentTest.cpp -common/rdm/DiscoveryAgentTestHelper.h -common/rdm/DummyResponder.cpp -common/rdm/FakeNetworkManager.cpp -common/rdm/FakeNetworkManager.h -common/rdm/GroupSizeCalculator.cpp -common/rdm/GroupSizeCalculator.h -common/rdm/GroupSizeCalculatorTest.cpp -common/rdm/MessageDeserializer.cpp -common/rdm/MessageDeserializerTest.cpp -common/rdm/MessageSerializer.cpp -common/rdm/MessageSerializerTest.cpp -common/rdm/MovingLightResponder.cpp -common/rdm/NetworkManager.cpp -common/rdm/NetworkManager.h -common/rdm/NetworkResponder.cpp -common/rdm/OpenLightingEnums.cpp -common/rdm/PidStore.cpp -common/rdm/PidStoreHelper.cpp -common/rdm/PidStoreLoader.cpp -common/rdm/PidStoreLoader.h -common/rdm/PidStoreTest.cpp -common/rdm/Pids.pb.cc -common/rdm/Pids.pb.h -common/rdm/QueueingRDMController.cpp -common/rdm/QueueingRDMControllerTest.cpp -common/rdm/RDMAPI.cpp -common/rdm/RDMAPITest.cpp -common/rdm/RDMCommand.cpp -common/rdm/RDMCommandSerializer.cpp -common/rdm/RDMCommandSerializerTest.cpp -common/rdm/RDMCommandTest.cpp -common/rdm/RDMFrame.cpp -common/rdm/RDMFrameTest.cpp -common/rdm/RDMHelper.cpp -common/rdm/RDMHelperTest.cpp -common/rdm/RDMMessageInterationTest.cpp -common/rdm/RDMReply.cpp -common/rdm/RDMReplyTest.cpp -common/rdm/ResponderHelper.cpp -common/rdm/ResponderLoadSensor.cpp -common/rdm/ResponderPersonality.cpp -common/rdm/ResponderSettings.cpp -common/rdm/ResponderSlotData.cpp -common/rdm/SensorResponder.cpp -common/rdm/StringMessageBuilder.cpp -common/rdm/StringMessageBuilderTest.cpp -common/rdm/SubDeviceDispatcher.cpp -common/rdm/TestHelper.h -common/rdm/UID.cpp -common/rdm/UIDAllocatorTest.cpp -common/rdm/UIDTest.cpp -common/rdm/VariableFieldSizeCalculator.cpp -common/rdm/VariableFieldSizeCalculator.h -common/rdm/VariableFieldSizeCalculatorTest.cpp -common/rpc/Rpc.pb.cc -common/rpc/Rpc.pb.h -common/rpc/RpcChannel.cpp -common/rpc/RpcChannel.h -common/rpc/RpcChannelTest.cpp -common/rpc/RpcController.cpp -common/rpc/RpcController.h -common/rpc/RpcControllerTest.cpp -common/rpc/RpcHeader.h -common/rpc/RpcHeaderTest.cpp -common/rpc/RpcPeer.h -common/rpc/RpcServer.cpp -common/rpc/RpcServer.h -common/rpc/RpcServerTest.cpp -common/rpc/RpcService.h -common/rpc/RpcSession.h -common/rpc/TestService.cpp -common/rpc/TestService.h -common/rpc/TestService.pb.cc -common/rpc/TestService.pb.h -common/rpc/TestServiceService.pb.cpp -common/rpc/TestServiceService.pb.h -common/strings/Format.cpp -common/strings/Utils.cpp -common/strings/UtilsTest.cpp -common/system/Limits.cpp -common/system/SystemUtils.cpp -common/testing/GenericTester.cpp -common/testing/MockUDPSocket.cpp -common/testing/TestUtils.cpp -common/thread/ConsumerThread.cpp -common/thread/ExecutorThread.cpp -common/thread/ExecutorThreadTest.cpp -common/thread/FutureTest.cpp -common/thread/Mutex.cpp -common/thread/PeriodicThread.cpp -common/thread/SignalThread.cpp -common/thread/Thread.cpp -common/thread/ThreadPool.cpp -common/thread/ThreadPoolTest.cpp -common/thread/ThreadTest.cpp -common/thread/Utils.cpp -common/timecode/TimeCode.cpp -common/timecode/TimeCodeTest.cpp -common/utils/ActionQueue.cpp -common/utils/ActionQueueTest.cpp -common/utils/BackoffTest.cpp -common/utils/CallbackTest.cpp -common/utils/Clock.cpp -common/utils/ClockTest.cpp -common/utils/DmxBuffer.cpp -common/utils/DmxBufferTest.cpp -common/utils/MultiCallbackTest.cpp -common/utils/StringUtils.cpp -common/utils/StringUtilsTest.cpp -common/utils/TokenBucket.cpp -common/utils/TokenBucketTest.cpp -common/utils/UtilsTest.cpp -common/utils/Watchdog.cpp -common/utils/WatchdogTest.cpp -common/web/Json.cpp -common/web/JsonData.cpp -common/web/JsonLexer.cpp -common/web/JsonParser.cpp -common/web/JsonPatch.cpp -common/web/JsonPatchParser.cpp -common/web/JsonPointer.cpp -common/web/JsonSchema.cpp -common/web/JsonSections.cpp -common/web/JsonTest.cpp -common/web/JsonTypes.cpp -common/web/JsonWriter.cpp -common/web/ParserTest.cpp -common/web/PatchParserTest.cpp -common/web/PatchTest.cpp -common/web/PointerTest.cpp -common/web/PointerTracker.cpp -common/web/PointerTracker.h -common/web/PointerTrackerTest.cpp -common/web/SchemaErrorLogger.cpp -common/web/SchemaErrorLogger.h -common/web/SchemaKeywords.cpp -common/web/SchemaKeywords.h -common/web/SchemaParseContext.cpp -common/web/SchemaParseContext.h -common/web/SchemaParser.cpp -common/web/SchemaParser.h -common/web/SchemaParserTest.cpp -common/web/SchemaTest.cpp -common/web/SectionsTest.cpp -config.h -data/rdm/PidDataTest.cpp -doxygen/examples/callback_client_transmit.cpp -doxygen/examples/client_disconnect.cpp -doxygen/examples/client_thread.cpp -doxygen/examples/fetch_plugins.cpp -doxygen/examples/flags.cpp -doxygen/examples/legacy_callback_client_transmit.cpp -doxygen/examples/legacy_receiver.cpp -doxygen/examples/legacy_streaming_client.cpp -doxygen/examples/receiver.cpp -doxygen/examples/stdin_handler.cpp -doxygen/examples/streaming_client.cpp -doxygen/examples/streaming_client_plugin.cpp -doxygen/examples/udp_server.cpp -examples/OlaConfigurator.cpp -examples/OlaConfigurator.h -examples/ShowLoader.cpp -examples/ShowLoader.h -examples/ShowPlayer.cpp -examples/ShowPlayer.h -examples/ShowRecorder.cpp -examples/ShowRecorder.h -examples/ShowSaver.cpp -examples/ShowSaver.h -examples/ola-artnet.cpp -examples/ola-client.cpp -examples/ola-dmxconsole.cpp -examples/ola-dmxmonitor.cpp -examples/ola-e131.cpp -examples/ola-latency.cpp -examples/ola-rdm-discover.cpp -examples/ola-rdm.cpp -examples/ola-recorder.cpp -examples/ola-streaming-client.cpp -examples/ola-throughput.cpp -examples/ola-timecode.cpp -examples/ola-uni-stats.cpp -examples/ola-usbpro.cpp -include/ola/ActionQueue.h -include/ola/BaseTypes.h -include/ola/Callback.h -include/ola/CallbackRunner.h -include/ola/Clock.h -include/ola/Constants.h -include/ola/DmxBuffer.h -include/ola/ExportMap.h -include/ola/Logging.h -include/ola/MultiCallback.h -include/ola/StringUtils.h -include/ola/acn/ACNPort.h -include/ola/acn/ACNVectors.h -include/ola/acn/CID.h -include/ola/base/Array.h -include/ola/base/Credentials.h -include/ola/base/Env.h -include/ola/base/Flags.h -include/ola/base/FlagsPrivate.h -include/ola/base/Init.h -include/ola/base/Macro.h -include/ola/base/SysExits.h -include/ola/base/Version.h -include/ola/client/CallbackTypes.h -include/ola/client/ClientArgs.h -include/ola/client/ClientRDMAPIShim.h -include/ola/client/ClientTypes.h -include/ola/client/ClientWrapper.h -include/ola/client/Module.h -include/ola/client/OlaClient.h -include/ola/client/Result.h -include/ola/client/StreamingClient.h -include/ola/dmx/RunLengthEncoder.h -include/ola/dmx/SourcePriorities.h -include/ola/e133/DeviceManager.h -include/ola/e133/E133Enums.h -include/ola/e133/E133Receiver.h -include/ola/e133/E133StatusHelper.h -include/ola/e133/E133URLParser.h -include/ola/e133/MessageBuilder.h -include/ola/file/Util.h -include/ola/http/HTTPServer.h -include/ola/http/OlaHTTPServer.h -include/ola/io/BigEndianStream.h -include/ola/io/ByteString.h -include/ola/io/Descriptor.h -include/ola/io/ExtendedSerial.h -include/ola/io/IOQueue.h -include/ola/io/IOStack.h -include/ola/io/IOUtils.h -include/ola/io/IOVecInterface.h -include/ola/io/InputBuffer.h -include/ola/io/InputStream.h -include/ola/io/MemoryBlock.h -include/ola/io/MemoryBlockPool.h -include/ola/io/MemoryBuffer.h -include/ola/io/NonBlockingSender.h -include/ola/io/OutputBuffer.h -include/ola/io/OutputStream.h -include/ola/io/SelectServer.h -include/ola/io/SelectServerInterface.h -include/ola/io/Serial.h -include/ola/io/StdinHandler.h -include/ola/math/Random.h -include/ola/messaging/Descriptor.h -include/ola/messaging/DescriptorVisitor.h -include/ola/messaging/Message.h -include/ola/messaging/MessagePrinter.h -include/ola/messaging/MessageVisitor.h -include/ola/messaging/SchemaPrinter.h -include/ola/messaging/StringMessageBuilder.h -include/ola/network/AdvancedTCPConnector.h -include/ola/network/HealthCheckedConnection.h -include/ola/network/IPV4Address.h -include/ola/network/Interface.h -include/ola/network/InterfacePicker.h -include/ola/network/MACAddress.h -include/ola/network/NetworkUtils.h -include/ola/network/Socket.h -include/ola/network/SocketAddress.h -include/ola/network/SocketCloser.h -include/ola/network/TCPConnector.h -include/ola/network/TCPSocket.h -include/ola/network/TCPSocketFactory.h -include/ola/plugin_id.h -include/ola/rdm/AckTimerResponder.h -include/ola/rdm/AdvancedDimmerResponder.h -include/ola/rdm/CommandPrinter.h -include/ola/rdm/DimmerResponder.h -include/ola/rdm/DimmerRootDevice.h -include/ola/rdm/DimmerSubDevice.h -include/ola/rdm/DiscoveryAgent.h -include/ola/rdm/DummyResponder.h -include/ola/rdm/MessageDeserializer.h -include/ola/rdm/MessageSerializer.h -include/ola/rdm/MovingLightResponder.h -include/ola/rdm/NetworkManagerInterface.h -include/ola/rdm/NetworkResponder.h -include/ola/rdm/OpenLightingEnums.h -include/ola/rdm/PidStore.h -include/ola/rdm/PidStoreHelper.h -include/ola/rdm/QueueingRDMController.h -include/ola/rdm/RDMAPI.h -include/ola/rdm/RDMAPIImplInterface.h -include/ola/rdm/RDMCommand.h -include/ola/rdm/RDMCommandSerializer.h -include/ola/rdm/RDMControllerAdaptor.h -include/ola/rdm/RDMControllerInterface.h -include/ola/rdm/RDMEnums.h -include/ola/rdm/RDMFrame.h -include/ola/rdm/RDMHelper.h -include/ola/rdm/RDMMessagePrinters.h -include/ola/rdm/RDMPacket.h -include/ola/rdm/RDMReply.h -include/ola/rdm/RDMResponseCodes.h -include/ola/rdm/ResponderHelper.h -include/ola/rdm/ResponderLoadSensor.h -include/ola/rdm/ResponderOps.h -include/ola/rdm/ResponderOpsPrivate.h -include/ola/rdm/ResponderPersonality.h -include/ola/rdm/ResponderSensor.h -include/ola/rdm/ResponderSettings.h -include/ola/rdm/ResponderSlotData.h -include/ola/rdm/SensorResponder.h -include/ola/rdm/StringMessageBuilder.h -include/ola/rdm/SubDeviceDispatcher.h -include/ola/rdm/UID.h -include/ola/rdm/UIDAllocator.h -include/ola/rdm/UIDSet.h -include/ola/rpc/RpcSessionHandler.h -include/ola/stl/STLUtils.h -include/ola/strings/Format.h -include/ola/strings/FormatPrivate.h -include/ola/strings/Utils.h -include/ola/system/Limits.h -include/ola/system/SystemUtils.h -include/ola/testing/MockUDPSocket.h -include/ola/testing/TestUtils.h -include/ola/thread/CallbackThread.h -include/ola/thread/ConsumerThread.h -include/ola/thread/ExecutorInterface.h -include/ola/thread/ExecutorThread.h -include/ola/thread/Future.h -include/ola/thread/FuturePrivate.h -include/ola/thread/Mutex.h -include/ola/thread/PeriodicThread.h -include/ola/thread/SchedulerInterface.h -include/ola/thread/SchedulingExecutorInterface.h -include/ola/thread/SignalThread.h -include/ola/thread/Thread.h -include/ola/thread/ThreadPool.h -include/ola/thread/Utils.h -include/ola/timecode/TimeCode.h -include/ola/timecode/TimeCodeEnums.h -include/ola/util/Backoff.h -include/ola/util/Deleter.h -include/ola/util/SequenceNumber.h -include/ola/util/Utils.h -include/ola/util/Watchdog.h -include/ola/web/Json.h -include/ola/web/JsonData.h -include/ola/web/JsonLexer.h -include/ola/web/JsonParser.h -include/ola/web/JsonPatch.h -include/ola/web/JsonPatchParser.h -include/ola/web/JsonPointer.h -include/ola/web/JsonSchema.h -include/ola/web/JsonSections.h -include/ola/web/JsonTypes.h -include/ola/web/JsonWriter.h -include/ola/web/OptionalItem.h -include/ola/win/CleanWinSock2.h -include/ola/win/CleanWindows.h -include/olad/Device.h -include/olad/DmxSource.h -include/olad/Plugin.h -include/olad/PluginAdaptor.h -include/olad/Port.h -include/olad/PortBroker.h -include/olad/PortConstants.h -include/olad/Preferences.h -include/olad/TokenBucket.h -include/olad/Universe.h -libs/acn/BaseInflator.cpp -libs/acn/BaseInflator.h -libs/acn/BaseInflatorTest.cpp -libs/acn/CID.cpp -libs/acn/CIDImpl.cpp -libs/acn/CIDImpl.h -libs/acn/CIDTest.cpp -libs/acn/DMPAddress.cpp -libs/acn/DMPAddress.h -libs/acn/DMPAddressTest.cpp -libs/acn/DMPE131Inflator.cpp -libs/acn/DMPE131Inflator.h -libs/acn/DMPHeader.h -libs/acn/DMPInflator.cpp -libs/acn/DMPInflator.h -libs/acn/DMPInflatorTest.cpp -libs/acn/DMPPDU.cpp -libs/acn/DMPPDU.h -libs/acn/DMPPDUTest.cpp -libs/acn/E131DiscoveryInflator.cpp -libs/acn/E131DiscoveryInflator.h -libs/acn/E131Header.h -libs/acn/E131Inflator.cpp -libs/acn/E131Inflator.h -libs/acn/E131InflatorTest.cpp -libs/acn/E131Node.cpp -libs/acn/E131Node.h -libs/acn/E131PDU.cpp -libs/acn/E131PDU.h -libs/acn/E131PDUTest.cpp -libs/acn/E131Sender.cpp -libs/acn/E131Sender.h -libs/acn/E131TestFramework.cpp -libs/acn/E131TestFramework.h -libs/acn/E133Header.h -libs/acn/E133Inflator.cpp -libs/acn/E133Inflator.h -libs/acn/E133InflatorTest.cpp -libs/acn/E133PDU.cpp -libs/acn/E133PDU.h -libs/acn/E133PDUTest.cpp -libs/acn/E133StatusInflator.cpp -libs/acn/E133StatusInflator.h -libs/acn/E133StatusPDU.cpp -libs/acn/E133StatusPDU.h -libs/acn/HeaderSet.h -libs/acn/HeaderSetTest.cpp -libs/acn/PDU.cpp -libs/acn/PDU.h -libs/acn/PDUTest.cpp -libs/acn/PDUTestCommon.h -libs/acn/PreamblePacker.cpp -libs/acn/PreamblePacker.h -libs/acn/RDMInflator.cpp -libs/acn/RDMInflator.h -libs/acn/RDMPDU.cpp -libs/acn/RDMPDU.h -libs/acn/RDMPDUTest.cpp -libs/acn/RootHeader.h -libs/acn/RootInflator.cpp -libs/acn/RootInflator.h -libs/acn/RootInflatorTest.cpp -libs/acn/RootPDU.cpp -libs/acn/RootPDU.h -libs/acn/RootPDUTest.cpp -libs/acn/RootSender.cpp -libs/acn/RootSender.h -libs/acn/RootSenderTest.cpp -libs/acn/TCPTransport.cpp -libs/acn/TCPTransport.h -libs/acn/TCPTransportTest.cpp -libs/acn/Transport.h -libs/acn/TransportHeader.h -libs/acn/UDPTransport.cpp -libs/acn/UDPTransport.h -libs/acn/UDPTransportTest.cpp -libs/acn/e131_loadtest.cpp -libs/acn/e131_transmit_test.cpp -libs/usb/HotplugAgent.cpp -libs/usb/HotplugAgent.h -libs/usb/JaRuleConstants.cpp -libs/usb/JaRuleConstants.h -libs/usb/JaRulePortHandle.cpp -libs/usb/JaRulePortHandle.h -libs/usb/JaRulePortHandleImpl.cpp -libs/usb/JaRulePortHandleImpl.h -libs/usb/JaRuleWidget.cpp -libs/usb/JaRuleWidget.h -libs/usb/JaRuleWidgetPort.cpp -libs/usb/JaRuleWidgetPort.h -libs/usb/LibUsbAdaptor.cpp -libs/usb/LibUsbAdaptor.h -libs/usb/LibUsbThread.cpp -libs/usb/LibUsbThread.h -libs/usb/LibUsbThreadTest.cpp -libs/usb/Types.cpp -libs/usb/Types.h -ola/AutoStart.cpp -ola/AutoStart.h -ola/ClientRDMAPIShim.cpp -ola/ClientTypesFactory.cpp -ola/ClientTypesFactory.h -ola/Module.cpp -ola/OlaCallbackClient.cpp -ola/OlaCallbackClient.h -ola/OlaClient.cpp -ola/OlaClientCore.cpp -ola/OlaClientCore.h -ola/OlaClientWrapper.cpp -ola/OlaClientWrapper.h -ola/OlaClientWrapperTest.cpp -ola/OlaDevice.h -ola/StreamingClient.cpp -ola/StreamingClient.h -ola/StreamingClientTest.cpp -olad/AvahiDiscoveryAgent.cpp -olad/AvahiDiscoveryAgent.h -olad/BonjourDiscoveryAgent.cpp -olad/BonjourDiscoveryAgent.h -olad/ClientBroker.cpp -olad/ClientBroker.h -olad/DiscoveryAgent.cpp -olad/DiscoveryAgent.h -olad/DynamicPluginLoader.cpp -olad/DynamicPluginLoader.h -olad/HttpServerActions.cpp -olad/HttpServerActions.h -olad/OlaDaemon.cpp -olad/OlaDaemon.h -olad/OlaServer.cpp -olad/OlaServer.h -olad/OlaServerServiceImpl.cpp -olad/OlaServerServiceImpl.h -olad/OlaServerServiceImplTest.cpp -olad/Olad.cpp -olad/OladHTTPServer.cpp -olad/OladHTTPServer.h -olad/PluginLoader.h -olad/PluginManager.cpp -olad/PluginManager.h -olad/PluginManagerTest.cpp -olad/RDMHTTPModule.cpp -olad/RDMHTTPModule.h -olad/plugin_api/Client.cpp -olad/plugin_api/Client.h -olad/plugin_api/ClientTest.cpp -olad/plugin_api/Device.cpp -olad/plugin_api/DeviceManager.cpp -olad/plugin_api/DeviceManager.h -olad/plugin_api/DeviceManagerTest.cpp -olad/plugin_api/DeviceTest.cpp -olad/plugin_api/DmxSource.cpp -olad/plugin_api/DmxSourceTest.cpp -olad/plugin_api/Plugin.cpp -olad/plugin_api/PluginAdaptor.cpp -olad/plugin_api/Port.cpp -olad/plugin_api/PortBroker.cpp -olad/plugin_api/PortManager.cpp -olad/plugin_api/PortManager.h -olad/plugin_api/PortManagerTest.cpp -olad/plugin_api/PortTest.cpp -olad/plugin_api/Preferences.cpp -olad/plugin_api/PreferencesTest.cpp -olad/plugin_api/TestCommon.h -olad/plugin_api/Universe.cpp -olad/plugin_api/UniverseStore.cpp -olad/plugin_api/UniverseStore.h -olad/plugin_api/UniverseTest.cpp -plugins/artnet/ArtNetDevice.cpp -plugins/artnet/ArtNetDevice.h -plugins/artnet/ArtNetNode.cpp -plugins/artnet/ArtNetNode.h -plugins/artnet/ArtNetNodeTest.cpp -plugins/artnet/ArtNetPackets.h -plugins/artnet/ArtNetPlugin.cpp -plugins/artnet/ArtNetPlugin.h -plugins/artnet/ArtNetPluginDescription.h -plugins/artnet/ArtNetPort.cpp -plugins/artnet/ArtNetPort.h -plugins/artnet/artnet_loadtest.cpp -plugins/artnet/messages/ArtNetConfigMessages.pb.cc -plugins/artnet/messages/ArtNetConfigMessages.pb.h -plugins/dmx4linux/Dmx4LinuxDevice.cpp -plugins/dmx4linux/Dmx4LinuxDevice.h -plugins/dmx4linux/Dmx4LinuxPlugin.cpp -plugins/dmx4linux/Dmx4LinuxPlugin.h -plugins/dmx4linux/Dmx4LinuxPort.cpp -plugins/dmx4linux/Dmx4LinuxPort.h -plugins/dmx4linux/Dmx4LinuxSocket.h -plugins/dummy/DummyDevice.cpp -plugins/dummy/DummyDevice.h -plugins/dummy/DummyPlugin.cpp -plugins/dummy/DummyPlugin.h -plugins/dummy/DummyPluginDescription.h -plugins/dummy/DummyPort.cpp -plugins/dummy/DummyPort.h -plugins/dummy/DummyPortTest.cpp -plugins/e131/E131Device.cpp -plugins/e131/E131Device.h -plugins/e131/E131Plugin.cpp -plugins/e131/E131Plugin.h -plugins/e131/E131PluginDescription.h -plugins/e131/E131Port.cpp -plugins/e131/E131Port.h -plugins/e131/messages/E131ConfigMessages.pb.cc -plugins/e131/messages/E131ConfigMessages.pb.h -plugins/espnet/EspNetDevice.cpp -plugins/espnet/EspNetDevice.h -plugins/espnet/EspNetNode.cpp -plugins/espnet/EspNetNode.h -plugins/espnet/EspNetPackets.h -plugins/espnet/EspNetPlugin.cpp -plugins/espnet/EspNetPlugin.h -plugins/espnet/EspNetPluginCommon.h -plugins/espnet/EspNetPluginDescription.h -plugins/espnet/EspNetPort.cpp -plugins/espnet/EspNetPort.h -plugins/espnet/RunLengthDecoder.cpp -plugins/espnet/RunLengthDecoder.h -plugins/espnet/RunLengthDecoderTest.cpp -plugins/ftdidmx/FtdiDmxDevice.cpp -plugins/ftdidmx/FtdiDmxDevice.h -plugins/ftdidmx/FtdiDmxPlugin.cpp -plugins/ftdidmx/FtdiDmxPlugin.h -plugins/ftdidmx/FtdiDmxPluginDescription.h -plugins/ftdidmx/FtdiDmxPort.h -plugins/ftdidmx/FtdiDmxThread.cpp -plugins/ftdidmx/FtdiDmxThread.h -plugins/ftdidmx/FtdiWidget.cpp -plugins/ftdidmx/FtdiWidget.h -plugins/gpio/GPIODevice.cpp -plugins/gpio/GPIODevice.h -plugins/gpio/GPIODriver.cpp -plugins/gpio/GPIODriver.h -plugins/gpio/GPIOPlugin.cpp -plugins/gpio/GPIOPlugin.h -plugins/gpio/GPIOPluginDescription.h -plugins/gpio/GPIOPort.cpp -plugins/gpio/GPIOPort.h -plugins/karate/KarateDevice.cpp -plugins/karate/KarateDevice.h -plugins/karate/KarateLight.cpp -plugins/karate/KarateLight.h -plugins/karate/KaratePlugin.cpp -plugins/karate/KaratePlugin.h -plugins/karate/KaratePluginDescription.h -plugins/karate/KaratePort.h -plugins/karate/KarateThread.cpp -plugins/karate/KarateThread.h -plugins/kinet/KiNetDevice.cpp -plugins/kinet/KiNetDevice.h -plugins/kinet/KiNetNode.cpp -plugins/kinet/KiNetNode.h -plugins/kinet/KiNetNodeTest.cpp -plugins/kinet/KiNetPlugin.cpp -plugins/kinet/KiNetPlugin.h -plugins/kinet/KiNetPluginDescription.h -plugins/kinet/KiNetPort.h -plugins/kinet/kinet.cpp -plugins/milinst/MilInstDevice.cpp -plugins/milinst/MilInstDevice.h -plugins/milinst/MilInstPlugin.cpp -plugins/milinst/MilInstPlugin.h -plugins/milinst/MilInstPluginDescription.h -plugins/milinst/MilInstPort.cpp -plugins/milinst/MilInstPort.h -plugins/milinst/MilInstWidget.cpp -plugins/milinst/MilInstWidget.h -plugins/milinst/MilInstWidget1463.cpp -plugins/milinst/MilInstWidget1463.h -plugins/milinst/MilInstWidget1553.cpp -plugins/milinst/MilInstWidget1553.h -plugins/nanoleaf/NanoleafDevice.cpp -plugins/nanoleaf/NanoleafDevice.h -plugins/nanoleaf/NanoleafNode.cpp -plugins/nanoleaf/NanoleafNode.h -plugins/nanoleaf/NanoleafNodeTest.cpp -plugins/nanoleaf/NanoleafPlugin.cpp -plugins/nanoleaf/NanoleafPlugin.h -plugins/nanoleaf/NanoleafPluginDescription.h -plugins/nanoleaf/NanoleafPort.h -plugins/opendmx/OpenDmxDevice.cpp -plugins/opendmx/OpenDmxDevice.h -plugins/opendmx/OpenDmxPlugin.cpp -plugins/opendmx/OpenDmxPlugin.h -plugins/opendmx/OpenDmxPluginDescription.h -plugins/opendmx/OpenDmxPort.h -plugins/opendmx/OpenDmxThread.cpp -plugins/opendmx/OpenDmxThread.h -plugins/openpixelcontrol/OPCClient.cpp -plugins/openpixelcontrol/OPCClient.h -plugins/openpixelcontrol/OPCClientTest.cpp -plugins/openpixelcontrol/OPCConstants.h -plugins/openpixelcontrol/OPCDevice.cpp -plugins/openpixelcontrol/OPCDevice.h -plugins/openpixelcontrol/OPCPlugin.cpp -plugins/openpixelcontrol/OPCPlugin.h -plugins/openpixelcontrol/OPCPluginDescription.h -plugins/openpixelcontrol/OPCPort.cpp -plugins/openpixelcontrol/OPCPort.h -plugins/openpixelcontrol/OPCServer.cpp -plugins/openpixelcontrol/OPCServer.h -plugins/openpixelcontrol/OPCServerTest.cpp -plugins/osc/OSCAddressTemplate.cpp -plugins/osc/OSCAddressTemplate.h -plugins/osc/OSCAddressTemplateTest.cpp -plugins/osc/OSCDevice.cpp -plugins/osc/OSCDevice.h -plugins/osc/OSCNode.cpp -plugins/osc/OSCNode.h -plugins/osc/OSCNodeTest.cpp -plugins/osc/OSCPlugin.cpp -plugins/osc/OSCPlugin.h -plugins/osc/OSCPort.cpp -plugins/osc/OSCPort.h -plugins/osc/OSCTarget.h -plugins/pathport/PathportDevice.cpp -plugins/pathport/PathportDevice.h -plugins/pathport/PathportNode.cpp -plugins/pathport/PathportNode.h -plugins/pathport/PathportPackets.h -plugins/pathport/PathportPlugin.cpp -plugins/pathport/PathportPlugin.h -plugins/pathport/PathportPluginDescription.h -plugins/pathport/PathportPort.cpp -plugins/pathport/PathportPort.h -plugins/renard/RenardDevice.cpp -plugins/renard/RenardDevice.h -plugins/renard/RenardPlugin.cpp -plugins/renard/RenardPlugin.h -plugins/renard/RenardPluginDescription.h -plugins/renard/RenardPort.cpp -plugins/renard/RenardPort.h -plugins/renard/RenardWidget.cpp -plugins/renard/RenardWidget.h -plugins/sandnet/SandNetCommon.h -plugins/sandnet/SandNetDevice.cpp -plugins/sandnet/SandNetDevice.h -plugins/sandnet/SandNetNode.cpp -plugins/sandnet/SandNetNode.h -plugins/sandnet/SandNetPackets.h -plugins/sandnet/SandNetPlugin.cpp -plugins/sandnet/SandNetPlugin.h -plugins/sandnet/SandNetPluginDescription.h -plugins/sandnet/SandNetPort.cpp -plugins/sandnet/SandNetPort.h -plugins/shownet/ShowNetDevice.cpp -plugins/shownet/ShowNetDevice.h -plugins/shownet/ShowNetNode.cpp -plugins/shownet/ShowNetNode.h -plugins/shownet/ShowNetNodeTest.cpp -plugins/shownet/ShowNetPackets.h -plugins/shownet/ShowNetPlugin.cpp -plugins/shownet/ShowNetPlugin.h -plugins/shownet/ShowNetPluginDescription.h -plugins/shownet/ShowNetPort.cpp -plugins/shownet/ShowNetPort.h -plugins/spi/FakeSPIWriter.cpp -plugins/spi/FakeSPIWriter.h -plugins/spi/SPIBackend.cpp -plugins/spi/SPIBackend.h -plugins/spi/SPIBackendTest.cpp -plugins/spi/SPIDevice.cpp -plugins/spi/SPIDevice.h -plugins/spi/SPIOutput.cpp -plugins/spi/SPIOutput.h -plugins/spi/SPIOutputTest.cpp -plugins/spi/SPIPlugin.cpp -plugins/spi/SPIPlugin.h -plugins/spi/SPIPluginDescription.h -plugins/spi/SPIPort.cpp -plugins/spi/SPIPort.h -plugins/spi/SPIWriter.cpp -plugins/spi/SPIWriter.h -plugins/spidmx/SPIDMXDevice.cpp -plugins/spidmx/SPIDMXDevice.h -plugins/spidmx/SPIDMXParser.cpp -plugins/spidmx/SPIDMXParser.h -plugins/spidmx/SPIDMXPlugin.cpp -plugins/spidmx/SPIDMXPlugin.h -plugins/spidmx/SPIDMXPluginDescription.h -plugins/spidmx/SPIDMXPort.h -plugins/spidmx/SPIDMXThread.cpp -plugins/spidmx/SPIDMXThread.h -plugins/spidmx/SPIDMXWidget.cpp -plugins/spidmx/SPIDMXWidget.h -plugins/stageprofi/StageProfiDetector.cpp -plugins/stageprofi/StageProfiDetector.h -plugins/stageprofi/StageProfiDevice.cpp -plugins/stageprofi/StageProfiDevice.h -plugins/stageprofi/StageProfiPlugin.cpp -plugins/stageprofi/StageProfiPlugin.h -plugins/stageprofi/StageProfiPluginDescription.h -plugins/stageprofi/StageProfiPort.cpp -plugins/stageprofi/StageProfiPort.h -plugins/stageprofi/StageProfiWidget.cpp -plugins/stageprofi/StageProfiWidget.h -plugins/uartdmx/UartDmxDevice.cpp -plugins/uartdmx/UartDmxDevice.h -plugins/uartdmx/UartDmxPlugin.cpp -plugins/uartdmx/UartDmxPlugin.h -plugins/uartdmx/UartDmxPluginDescription.h -plugins/uartdmx/UartDmxPort.h -plugins/uartdmx/UartDmxThread.cpp -plugins/uartdmx/UartDmxThread.h -plugins/uartdmx/UartWidget.cpp -plugins/uartdmx/UartWidget.h -plugins/usbdmx/AVLdiyD512.cpp -plugins/usbdmx/AVLdiyD512.h -plugins/usbdmx/AVLdiyD512Factory.cpp -plugins/usbdmx/AVLdiyD512Factory.h -plugins/usbdmx/AnymauDMX.cpp -plugins/usbdmx/AnymauDMX.h -plugins/usbdmx/AnymauDMXFactory.cpp -plugins/usbdmx/AnymauDMXFactory.h -plugins/usbdmx/AsyncPluginImpl.cpp -plugins/usbdmx/AsyncPluginImpl.h -plugins/usbdmx/AsyncUsbReceiver.cpp -plugins/usbdmx/AsyncUsbReceiver.h -plugins/usbdmx/AsyncUsbSender.cpp -plugins/usbdmx/AsyncUsbSender.h -plugins/usbdmx/AsyncUsbTransceiverBase.cpp -plugins/usbdmx/AsyncUsbTransceiverBase.h -plugins/usbdmx/DMXCProjectsNodleU1.cpp -plugins/usbdmx/DMXCProjectsNodleU1.h -plugins/usbdmx/DMXCProjectsNodleU1Device.cpp -plugins/usbdmx/DMXCProjectsNodleU1Device.h -plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp -plugins/usbdmx/DMXCProjectsNodleU1Factory.h -plugins/usbdmx/DMXCProjectsNodleU1Port.cpp -plugins/usbdmx/DMXCProjectsNodleU1Port.h -plugins/usbdmx/DMXCreator512Basic.cpp -plugins/usbdmx/DMXCreator512Basic.h -plugins/usbdmx/DMXCreator512BasicFactory.cpp -plugins/usbdmx/DMXCreator512BasicFactory.h -plugins/usbdmx/EurolitePro.cpp -plugins/usbdmx/EurolitePro.h -plugins/usbdmx/EuroliteProFactory.cpp -plugins/usbdmx/EuroliteProFactory.h -plugins/usbdmx/FirmwareLoader.h -plugins/usbdmx/Flags.cpp -plugins/usbdmx/GenericDevice.cpp -plugins/usbdmx/GenericDevice.h -plugins/usbdmx/GenericOutputPort.cpp -plugins/usbdmx/GenericOutputPort.h -plugins/usbdmx/JaRuleDevice.cpp -plugins/usbdmx/JaRuleDevice.h -plugins/usbdmx/JaRuleFactory.cpp -plugins/usbdmx/JaRuleFactory.h -plugins/usbdmx/JaRuleOutputPort.cpp -plugins/usbdmx/JaRuleOutputPort.h -plugins/usbdmx/PluginImplInterface.h -plugins/usbdmx/ScanlimeFadecandy.cpp -plugins/usbdmx/ScanlimeFadecandy.h -plugins/usbdmx/ScanlimeFadecandyFactory.cpp -plugins/usbdmx/ScanlimeFadecandyFactory.h -plugins/usbdmx/ShowJockeyDMXU1.cpp -plugins/usbdmx/ShowJockeyDMXU1.h -plugins/usbdmx/ShowJockeyDMXU1Factory.cpp -plugins/usbdmx/ShowJockeyDMXU1Factory.h -plugins/usbdmx/Sunlite.cpp -plugins/usbdmx/Sunlite.h -plugins/usbdmx/SunliteFactory.cpp -plugins/usbdmx/SunliteFactory.h -plugins/usbdmx/SunliteFirmware.h -plugins/usbdmx/SunliteFirmwareLoader.cpp -plugins/usbdmx/SunliteFirmwareLoader.h -plugins/usbdmx/SyncPluginImpl.cpp -plugins/usbdmx/SyncPluginImpl.h -plugins/usbdmx/SynchronizedWidgetObserver.cpp -plugins/usbdmx/SynchronizedWidgetObserver.h -plugins/usbdmx/ThreadedUsbReceiver.cpp -plugins/usbdmx/ThreadedUsbReceiver.h -plugins/usbdmx/ThreadedUsbSender.cpp -plugins/usbdmx/ThreadedUsbSender.h -plugins/usbdmx/UsbDmxPlugin.cpp -plugins/usbdmx/UsbDmxPlugin.h -plugins/usbdmx/UsbDmxPluginDescription.h -plugins/usbdmx/VellemanK8062.cpp -plugins/usbdmx/VellemanK8062.h -plugins/usbdmx/VellemanK8062Factory.cpp -plugins/usbdmx/VellemanK8062Factory.h -plugins/usbdmx/Widget.h -plugins/usbdmx/WidgetFactory.h -plugins/usbpro/ArduinoRGBDevice.cpp -plugins/usbpro/ArduinoRGBDevice.h -plugins/usbpro/ArduinoWidget.cpp -plugins/usbpro/ArduinoWidget.h -plugins/usbpro/ArduinoWidgetTest.cpp -plugins/usbpro/BaseRobeWidget.cpp -plugins/usbpro/BaseRobeWidget.h -plugins/usbpro/BaseRobeWidgetTest.cpp -plugins/usbpro/BaseUsbProWidget.cpp -plugins/usbpro/BaseUsbProWidget.h -plugins/usbpro/BaseUsbProWidgetTest.cpp -plugins/usbpro/CommonWidgetTest.cpp -plugins/usbpro/CommonWidgetTest.h -plugins/usbpro/DmxTriDevice.cpp -plugins/usbpro/DmxTriDevice.h -plugins/usbpro/DmxTriWidget.cpp -plugins/usbpro/DmxTriWidget.h -plugins/usbpro/DmxTriWidgetTest.cpp -plugins/usbpro/DmxterDevice.cpp -plugins/usbpro/DmxterDevice.h -plugins/usbpro/DmxterWidget.cpp -plugins/usbpro/DmxterWidget.h -plugins/usbpro/DmxterWidgetTest.cpp -plugins/usbpro/EnttecUsbProWidget.cpp -plugins/usbpro/EnttecUsbProWidget.h -plugins/usbpro/EnttecUsbProWidgetImpl.h -plugins/usbpro/EnttecUsbProWidgetTest.cpp -plugins/usbpro/GenericUsbProWidget.cpp -plugins/usbpro/GenericUsbProWidget.h -plugins/usbpro/MockEndpoint.cpp -plugins/usbpro/MockEndpoint.h -plugins/usbpro/RobeDevice.cpp -plugins/usbpro/RobeDevice.h -plugins/usbpro/RobeWidget.cpp -plugins/usbpro/RobeWidget.h -plugins/usbpro/RobeWidgetDetector.cpp -plugins/usbpro/RobeWidgetDetector.h -plugins/usbpro/RobeWidgetDetectorTest.cpp -plugins/usbpro/RobeWidgetTest.cpp -plugins/usbpro/SerialWidgetInterface.h -plugins/usbpro/UltraDMXProDevice.cpp -plugins/usbpro/UltraDMXProDevice.h -plugins/usbpro/UltraDMXProWidget.cpp -plugins/usbpro/UltraDMXProWidget.h -plugins/usbpro/UltraDMXProWidgetTest.cpp -plugins/usbpro/UsbProDevice.cpp -plugins/usbpro/UsbProDevice.h -plugins/usbpro/UsbProWidgetDetector.cpp -plugins/usbpro/UsbProWidgetDetector.h -plugins/usbpro/UsbProWidgetDetectorTest.cpp -plugins/usbpro/UsbSerialDevice.h -plugins/usbpro/UsbSerialPlugin.cpp -plugins/usbpro/UsbSerialPlugin.h -plugins/usbpro/UsbSerialPluginDescription.h -plugins/usbpro/WidgetDetectorInterface.h -plugins/usbpro/WidgetDetectorThread.cpp -plugins/usbpro/WidgetDetectorThread.h -plugins/usbpro/WidgetDetectorThreadTest.cpp -plugins/usbpro/messages/UsbProConfigMessages.pb.cc -plugins/usbpro/messages/UsbProConfigMessages.pb.h -protoc/CppFileGenerator.cpp -protoc/CppFileGenerator.h -protoc/CppGenerator.cpp -protoc/CppGenerator.h -protoc/GeneratorHelpers.cpp -protoc/GeneratorHelpers.h -protoc/ServiceGenerator.cpp -protoc/ServiceGenerator.h -protoc/StrUtil.cpp -protoc/StrUtil.h -protoc/ola-protoc-generator-plugin.cpp -tools/e133/DesignatedControllerConnection.cpp -tools/e133/DesignatedControllerConnection.h -tools/e133/DeviceManager.cpp -tools/e133/DeviceManagerImpl.cpp -tools/e133/DeviceManagerImpl.h -tools/e133/E133Device.cpp -tools/e133/E133Device.h -tools/e133/E133Endpoint.cpp -tools/e133/E133Endpoint.h -tools/e133/E133HealthCheckedConnection.cpp -tools/e133/E133HealthCheckedConnection.h -tools/e133/E133Receiver.cpp -tools/e133/E133StatusHelper.cpp -tools/e133/EndpointManager.cpp -tools/e133/EndpointManager.h -tools/e133/ManagementEndpoint.cpp -tools/e133/ManagementEndpoint.h -tools/e133/MessageBuilder.cpp -tools/e133/SimpleE133Node.cpp -tools/e133/SimpleE133Node.h -tools/e133/TCPConnectionStats.h -tools/e133/basic-controller.cpp -tools/e133/basic-device.cpp -tools/e133/e133-controller.cpp -tools/e133/e133-monitor.cpp -tools/e133/e133-receiver.cpp -tools/ja-rule/USBDeviceManager.cpp -tools/ja-rule/USBDeviceManager.h -tools/ja-rule/ja-rule-controller.cpp -tools/ja-rule/ja-rule.cpp -tools/logic/DMXSignalProcessor.cpp -tools/logic/DMXSignalProcessor.h -tools/logic/logic-rdm-sniffer.cpp -tools/ola_trigger/Action.cpp -tools/ola_trigger/Action.h -tools/ola_trigger/ActionTest.cpp -tools/ola_trigger/ConfigCommon.h -tools/ola_trigger/Context.cpp -tools/ola_trigger/Context.h -tools/ola_trigger/ContextTest.cpp -tools/ola_trigger/DMXTrigger.cpp -tools/ola_trigger/DMXTrigger.h -tools/ola_trigger/DMXTriggerTest.cpp -tools/ola_trigger/IntervalTest.cpp -tools/ola_trigger/MockAction.h -tools/ola_trigger/ParserActions.cpp -tools/ola_trigger/ParserActions.h -tools/ola_trigger/ParserGlobals.h -tools/ola_trigger/SlotTest.cpp -tools/ola_trigger/VariableInterpolator.cpp -tools/ola_trigger/VariableInterpolator.h -tools/ola_trigger/VariableInterpolatorTest.cpp -tools/ola_trigger/config.tab.cpp -tools/ola_trigger/config.tab.h -tools/ola_trigger/lex.yy.cpp -tools/ola_trigger/ola-trigger.cpp -tools/rdmpro/rdm-sniffer.cpp -tools/usbpro/usbpro-firmware.cpp diff --git a/OLA.includes b/OLA.includes deleted file mode 100644 index 71af031e80..0000000000 --- a/OLA.includes +++ /dev/null @@ -1,69 +0,0 @@ -. -common/io -common/network -common/protocol -common/rdm -common/rpc -common/web -examples -include/ola -include/ola/acn -include/ola/base -include/ola/client -include/ola/dmx -include/ola/e133 -include/ola/file -include/ola/http -include/ola/io -include/ola/math -include/ola/messaging -include/ola/network -include/ola/rdm -include/ola/rpc -include/ola/stl -include/ola/strings -include/ola/system -include/ola/testing -include/ola/thread -include/ola/timecode -include/ola/util -include/ola/web -include/ola/win -include/olad -libs/acn -libs/usb -ola -olad -olad/plugin_api -plugins/artnet -plugins/artnet/messages -plugins/dmx4linux -plugins/dummy -plugins/e131 -plugins/e131/messages -plugins/espnet -plugins/ftdidmx -plugins/gpio -plugins/karate -plugins/kinet -plugins/milinst -plugins/nanoleaf -plugins/opendmx -plugins/openpixelcontrol -plugins/osc -plugins/pathport -plugins/renard -plugins/sandnet -plugins/shownet -plugins/spi -plugins/spidmx -plugins/stageprofi -plugins/uartdmx -plugins/usbdmx -plugins/usbpro -plugins/usbpro/messages -protoc -tools/e133 -tools/ja-rule -tools/logic -tools/ola_trigger diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index ef0eb62f58..7df1f7fad3 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -94,6 +94,7 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { + OLA_INFO << "Sending RDM Request #" << m_transaction_number; request->SetTransactionNumber(m_transaction_number += 1); m_RDMQueue.push(std::pair(request, callback)); From 1bdf89752504f3406ad3975d072c44f0cd2aa2ff Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 28 Dec 2018 03:09:57 +0200 Subject: [PATCH 07/86] Simplified RDM implementation only implement the discovery interface It still doesn't work and some behaviors are plain wrong (the callbacks being called when stuff can't get to the line) Sadly my second FTDI interface is broken so I can't currently check if RDM packets are actually hitting the line or not. Also still leaves olad that doesn't shutdown without kill -9. --- plugins/ftdidmx/FtdiDmxThread.cpp | 135 ++++++++++++++++-------------- plugins/ftdidmx/FtdiDmxThread.h | 8 +- 2 files changed, 77 insertions(+), 66 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 7df1f7fad3..98bd2e1d45 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -53,8 +53,9 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency) m_term(false), m_frequency(frequency), m_transaction_number(0), - m_discovery_agent(this), m_uid(0x7a70, 0x12345678), + m_pending_request(nullptr), + m_rdm_callback(nullptr), m_mute_complete(nullptr), m_unmute_complete(nullptr), m_branch_callback(nullptr) { @@ -71,11 +72,9 @@ FtdiDmxThread::~FtdiDmxThread() { bool FtdiDmxThread::Stop() { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; - while(!m_RDMQueue.empty()){ - OLA_INFO << "Emptying Queue"; - //delete m_RDMQueue.front().first; - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); - m_RDMQueue.pop(); + + if(m_pending_request != nullptr) { + //destroy pending request and callbacks } return Join(); } @@ -94,33 +93,46 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { - OLA_INFO << "Sending RDM Request #" << m_transaction_number; - request->SetTransactionNumber(m_transaction_number += 1); - m_RDMQueue.push(std::pair(request, callback)); + ola::thread::MutexLocker locker(&m_rdm_mutex); + if(m_pending_request == nullptr) { + m_pending_request = request; + m_rdm_callback = callback; + } + OLA_WARN << "Function not properly implemented yet, callback won't get called."; } void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { - if(m_mute_complete == nullptr) { + ola::thread::MutexLocker locker(&m_rdm_mutex); + if(m_pending_request == nullptr) { + OLA_INFO << "Muting device"; m_mute_complete = mute_complete; - SendRDMRequest(ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1), nullptr); + m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1); + } else { + // Already pending request } } void FtdiDmxThread::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { - if(m_unmute_complete == nullptr){ + ola::thread::MutexLocker locker(&m_rdm_mutex); + if(m_pending_request == nullptr) { + OLA_INFO << "Sending UnMuteAll"; m_unmute_complete = unmute_complete; - SendRDMRequest(ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number += 1), nullptr); + m_pending_request = ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number += 1); + } else { + // Already pending request } } void FtdiDmxThread::Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { - if(m_branch_callback == nullptr) { + ola::thread::MutexLocker locker(&m_rdm_mutex); + if(m_pending_request == nullptr) { m_branch_callback = callback; - SendRDMRequest(ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1), nullptr); + m_pending_request = ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1); + } else { + // Already pending request } } @@ -128,6 +140,7 @@ void FtdiDmxThread::Branch(const ola::rdm::UID &lower, * @brief The method called by the thread */ void *FtdiDmxThread::Run() { + OLA_INFO << "Starting FtdiDmxThread"; TimeStamp ts1, ts2, ts3, lastDMX; Clock clock; CheckTimeGranularity(); @@ -137,6 +150,7 @@ void *FtdiDmxThread::Run() { int readBytes; unsigned char readBuffer[258]; ola::io::ByteString packetBuffer; + MuteDeviceCallback *thread_mute_callback = nullptr; UnMuteDeviceCallback *thread_unmute_callback = nullptr; BranchCallback *thread_branch_callback = nullptr; @@ -164,22 +178,39 @@ void *FtdiDmxThread::Run() { } clock.CurrentTime(&ts1); - if(!m_RDMQueue.empty()) { + if(m_pending_request != nullptr) { + elapsed = ts1 - lastDMX; + if(elapsed.InMilliSeconds() < 500) { - if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_RDMQueue.front().first, &packetBuffer)) { + + if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; - delete m_RDMQueue.front().first; - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); - m_RDMQueue.pop(); + delete m_pending_request; + m_pending_request = nullptr; + + // This behavior is wrong, this suggests to whoever is doing the discovery that no devices are connected/responding while we actually just failed to get the packet to the line. + if(m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + thread_mute_callback->Run(false); + } else if(m_unmute_complete != nullptr) { + thread_unmute_callback = m_unmute_complete; + m_unmute_complete = nullptr; + thread_unmute_callback->Run(); + } else if(m_branch_callback != nullptr) { + thread_branch_callback = m_branch_callback; + m_branch_callback = nullptr; + thread_branch_callback->Run(nullptr, 0); + } sendRDM = false; } else { + OLA_INFO << "OK To send RDM"; sendRDM = true; } } } - if (!m_interface->SetBreak(true)) { goto framesleep; } @@ -204,61 +235,41 @@ void *FtdiDmxThread::Run() { } } else { if(m_interface->Write(&packetBuffer)) { - if(m_RDMQueue.front().first->IsDUB()) { - thread_branch_callback = m_branch_callback; - m_branch_callback = nullptr; - - usleep(1400); + if(m_pending_request->IsDUB()) { + usleep(58000); //min time before next packet broadcast allowed readBytes = m_interface->Read(readBuffer, 258); - // also catches hw issues, slightly incorrect, but they were already reported at hw layer. - if(readBytes < 0) { - //RunRDMCallback(thread_branch_callback, rdm::RDM_TIMEOUT); - } else if (readBytes <= 24) {// Ignores potential for bad splitters dropping preamble bytes. + if(m_branch_callback != nullptr) { + thread_branch_callback = m_branch_callback; + m_branch_callback = nullptr; thread_branch_callback->Run(readBuffer, readBytes); - thread_branch_callback = nullptr; - } else { - // Invalid response (collision) } - } else if(!m_RDMQueue.front().first->DestinationUID().IsBroadcast()) { - // Wait half the time needed for broadcasting 512 bytes (full packet which is impossible in RDM) - usleep(31000); + } + else if(!m_pending_request->DestinationUID().IsBroadcast()) { + usleep(30000); //min time before next packet allowed readBytes = m_interface->Read(readBuffer, 258); - // also catches hw issues, slightly incorrect, but they were already reported at hw layer. - if(readBytes <= 0) { - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_TIMEOUT); - } else { - // The following block of code makes the assumption that only 1 callback pointer will be set at the same time, - // this assumption is patently false but we are hacking things to get an initial POC - if (m_RDMQueue.front().second != nullptr) { - m_RDMQueue.front().second->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_RDMQueue.front().first)); - } else if (m_mute_complete != nullptr) { - thread_mute_callback = m_mute_complete; - m_mute_complete = nullptr; - if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_RDMQueue.front().first->DestinationUID()) { - thread_mute_callback->Run(true); - } else { - thread_mute_callback->Run(false); - } - thread_mute_callback = nullptr; + if(m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + + if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + thread_mute_callback->Run(true); + } else { + thread_mute_callback->Run(false); } } + } else { - if (m_RDMQueue.front().second != nullptr) { - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_WAS_BROADCAST); - } else if(m_unmute_complete != nullptr) { + if(m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; thread_unmute_callback->Run(); - thread_unmute_callback = nullptr; } } } else { - if (m_RDMQueue.front().second != nullptr) { - RunRDMCallback(m_RDMQueue.front().second, rdm::RDM_FAILED_TO_SEND); - } else if(m_branch_callback != nullptr) { + if(m_branch_callback != nullptr) { } else if(m_mute_complete != nullptr) { @@ -266,7 +277,7 @@ void *FtdiDmxThread::Run() { } } - m_RDMQueue.pop(); + goto framesleep; } diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index d076c81db7..40c5e6336b 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -73,18 +73,18 @@ class FtdiDmxThread DmxBuffer m_buffer; ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; + ola::thread::Mutex m_rdm_mutex; uint8_t m_transaction_number; - ola::rdm::DiscoveryAgent m_discovery_agent; + //ola::rdm::DiscoveryAgent m_discovery_agent; const ola::rdm::UID m_uid; + ola::rdm::RDMRequest *m_pending_request; + ola::rdm::RDMCallback *m_rdm_callback; MuteDeviceCallback *m_mute_complete; UnMuteDeviceCallback *m_unmute_complete; BranchCallback *m_branch_callback; - std::queue> m_RDMQueue; - void CheckTimeGranularity(); static const uint32_t DMX_MAB = 16; From 8553598f603ccc3c834c91124188654065884c66 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 02:22:20 +0200 Subject: [PATCH 08/86] Another attempt with no fruits... Added the DiscoveryAgent and inheritance from DiscoverableRDMControllerInterface --- plugins/ftdidmx/FtdiDmxPort.h | 3 +++ plugins/ftdidmx/FtdiDmxThread.cpp | 27 +++++++++++++++++++++++++++ plugins/ftdidmx/FtdiDmxThread.h | 9 ++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index d7c7b5544a..52e7f472df 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -74,16 +74,19 @@ class FtdiDmxOutputPort void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete){ + OLA_WARN << "Port.MuteDevice()"; m_thread.MuteDevice(target, mute_complete); } void UnMuteAll(UnMuteDeviceCallback *unmute_complete) { + OLA_WARN << "Port.UnMuteAll()"; m_thread.UnMuteAll(unmute_complete); } void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { + OLA_WARN << "Port.Branch()"; m_thread.Branch(lower, upper, callback); } diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 98bd2e1d45..7a41da3e5d 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -53,6 +53,7 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency) m_term(false), m_frequency(frequency), m_transaction_number(0), + m_discovery_agent(this), m_uid(0x7a70, 0x12345678), m_pending_request(nullptr), m_rdm_callback(nullptr), @@ -101,6 +102,31 @@ void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, OLA_WARN << "Function not properly implemented yet, callback won't get called."; } +void FtdiDmxThread::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { + m_discovery_agent.StartFullDiscovery(ola::NewSingleCallback(this, &FtdiDmxThread::DiscoveryComplete, callback)); +} + +void FtdiDmxThread::RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { + m_discovery_agent.StartIncrementalDiscovery(ola::NewSingleCallback(this, &FtdiDmxThread::DiscoveryComplete, callback)); +} + +/** + * Called when the discovery process finally completes + * @param callback the callback passed to StartFullDiscovery or + * StartIncrementalDiscovery that we should execute. + * @param status true if discovery worked, false otherwise + * @param uids the UIDSet of UIDs that were found. + */ +void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, + bool, + const ola::rdm::UIDSet &uids) { + OLA_DEBUG << "FTDI discovery complete: " << uids; + if (callback) { + callback->Run(uids); + } +} + + void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { ola::thread::MutexLocker locker(&m_rdm_mutex); @@ -129,6 +155,7 @@ void FtdiDmxThread::Branch(const ola::rdm::UID &lower, BranchCallback *callback) { ola::thread::MutexLocker locker(&m_rdm_mutex); if(m_pending_request == nullptr) { + OLA_INFO << "Sending branch"; m_branch_callback = callback; m_pending_request = ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1); } else { diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 40c5e6336b..565f64f044 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -41,6 +41,7 @@ namespace ftdidmx { class FtdiDmxThread : public ola::thread::Thread, + public ola::rdm::DiscoverableRDMControllerInterface, public ola::rdm::DiscoveryTargetInterface { public: FtdiDmxThread(FtdiInterface *interface, unsigned int frequency); @@ -52,6 +53,9 @@ class FtdiDmxThread void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); + void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); + void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); + void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete); @@ -76,7 +80,7 @@ class FtdiDmxThread ola::thread::Mutex m_rdm_mutex; uint8_t m_transaction_number; - //ola::rdm::DiscoveryAgent m_discovery_agent; + ola::rdm::DiscoveryAgent m_discovery_agent; const ola::rdm::UID m_uid; ola::rdm::RDMRequest *m_pending_request; @@ -86,6 +90,9 @@ class FtdiDmxThread BranchCallback *m_branch_callback; void CheckTimeGranularity(); + void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, + bool status, + const ola::rdm::UIDSet &uids); static const uint32_t DMX_MAB = 16; static const uint32_t DMX_BREAK = 110; From 81d120b0464d7f97a41294ee5e6e5119b6310612 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 14:28:36 +0200 Subject: [PATCH 09/86] Added discovery functions to port, now stuff actually gets called. --- plugins/ftdidmx/FtdiDmxPort.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 52e7f472df..d7feeaa067 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -70,6 +70,13 @@ class FtdiDmxOutputPort m_thread.SendRDMRequest(request, callback); } + void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { + m_thread.RunFullDiscovery(callback); + } + void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { + m_thread.RunIncrementalDiscovery(callback); + } + std::string Description() const { return m_interface->Description(); } void MuteDevice(const ola::rdm::UID &target, From 8914f56da5b631c3658206eca8abafc63033655f Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 14:30:19 +0200 Subject: [PATCH 10/86] Some debug output plus detect that less bytes were written then requested --- plugins/ftdidmx/FtdiWidget.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 74601c2cab..806e3b39f7 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -369,12 +369,18 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { bool FtdiInterface::Write(ola::io::ByteString *packet) { - if(ftdi_write_data(&m_handle, packet->data(), packet->size()) < 0) { + int bytesWritten = ftdi_write_data(&m_handle, packet->data(), packet->size()); + int size = packet->size(); + if(bytesWritten < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; - } else { + } else if (bytesWritten == (int)packet->size()){ return true; + } else { + OLA_WARN << "Bytes Written: " << bytesWritten; + OLA_WARN << "Packet Size: " << size; + return false; } } From 9e958249571a47a408dece75e867d3a256ce3b32 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 14:31:02 +0200 Subject: [PATCH 11/86] Some logic fixes that came up now that discovery actually tries to run. At this point only UnMuteAll gets called, after its' callback is fired no further RDM packets are sent. Also I'm pretty sure I may be leaking some memory. --- plugins/ftdidmx/FtdiDmxThread.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 7a41da3e5d..6e1b20755e 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -213,7 +213,6 @@ void *FtdiDmxThread::Run() { if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; - delete m_pending_request; m_pending_request = nullptr; // This behavior is wrong, this suggests to whoever is doing the discovery that no devices are connected/responding while we actually just failed to get the packet to the line. @@ -235,7 +234,11 @@ void *FtdiDmxThread::Run() { OLA_INFO << "OK To send RDM"; sendRDM = true; } + } else { + sendRDM = false; } + } else { + sendRDM = false; } if (!m_interface->SetBreak(true)) { @@ -262,6 +265,7 @@ void *FtdiDmxThread::Run() { } } else { if(m_interface->Write(&packetBuffer)) { + OLA_INFO << "RDM packet"; if(m_pending_request->IsDUB()) { usleep(58000); //min time before next packet broadcast allowed readBytes = m_interface->Read(readBuffer, 258); @@ -292,9 +296,11 @@ void *FtdiDmxThread::Run() { if(m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; + OLA_INFO << "UnMuteAllCallback"; thread_unmute_callback->Run(); } } + m_pending_request = nullptr; } else { if(m_branch_callback != nullptr) { From ff09297f49f285f85ed6802f59aeb0cc44df6940 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 19:00:50 +0200 Subject: [PATCH 12/86] Clean up Port and remove functions not needed. --- plugins/ftdidmx/FtdiDmxPort.h | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index d7feeaa067..65b888fbe0 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -44,8 +44,7 @@ namespace plugin { namespace ftdidmx { class FtdiDmxOutputPort - : public ola::BasicOutputPort, - public ola::rdm::DiscoveryTargetInterface { + : public ola::BasicOutputPort { public: FtdiDmxOutputPort(FtdiDmxDevice *parent, FtdiInterface *interface, @@ -79,24 +78,6 @@ class FtdiDmxOutputPort std::string Description() const { return m_interface->Description(); } - void MuteDevice(const ola::rdm::UID &target, - MuteDeviceCallback *mute_complete){ - OLA_WARN << "Port.MuteDevice()"; - m_thread.MuteDevice(target, mute_complete); - } - - void UnMuteAll(UnMuteDeviceCallback *unmute_complete) { - OLA_WARN << "Port.UnMuteAll()"; - m_thread.UnMuteAll(unmute_complete); - } - - void Branch(const ola::rdm::UID &lower, - const ola::rdm::UID &upper, - BranchCallback *callback) { - OLA_WARN << "Port.Branch()"; - m_thread.Branch(lower, upper, callback); - } - private: FtdiInterface *m_interface; FtdiDmxThread m_thread; From 851401b6761f2f510c6f5babcb06d82f7b7df0fe Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 19:01:55 +0200 Subject: [PATCH 13/86] Minor cosmetic change --- plugins/ftdidmx/FtdiWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 806e3b39f7..90e27483a6 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -378,8 +378,7 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { } else if (bytesWritten == (int)packet->size()){ return true; } else { - OLA_WARN << "Bytes Written: " << bytesWritten; - OLA_WARN << "Packet Size: " << size; + OLA_WARN << "Bytes Written: " << bytesWritten << " Packet Size: " << size; return false; } } From 1d09fe10db0c2077e4c742945a362158ede50c6c Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 8 Jan 2019 19:23:29 +0200 Subject: [PATCH 14/86] Added some of the RDMReply callback logic. Added some more debug output for when an operation is pending/ --- plugins/ftdidmx/FtdiDmxThread.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 6e1b20755e..e884a786bf 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -98,8 +98,10 @@ void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, if(m_pending_request == nullptr) { m_pending_request = request; m_rdm_callback = callback; + } else { + OLA_WARN << "Unable to queue RDM request, RDM operation already pending"; } - OLA_WARN << "Function not properly implemented yet, callback won't get called."; + OLA_WARN << "Function not properly implemented yet, callback may not get called."; } void FtdiDmxThread::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { @@ -136,6 +138,7 @@ void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1); } else { // Already pending request + } } @@ -147,6 +150,7 @@ void FtdiDmxThread::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { m_pending_request = ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number += 1); } else { // Already pending request + OLA_WARN << "Unable to queue UnMuteAll request, RDM operation already pending"; } } @@ -160,6 +164,7 @@ void FtdiDmxThread::Branch(const ola::rdm::UID &lower, m_pending_request = ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1); } else { // Already pending request + OLA_WARN << "Unable to queue Branch request, RDM operation already pending"; } } @@ -181,6 +186,7 @@ void *FtdiDmxThread::Run() { MuteDeviceCallback *thread_mute_callback = nullptr; UnMuteDeviceCallback *thread_unmute_callback = nullptr; BranchCallback *thread_branch_callback = nullptr; + ola::rdm::RDMCallback *thread_rdm_callback = nullptr; int frameTime = static_cast(floor( @@ -228,6 +234,10 @@ void *FtdiDmxThread::Run() { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; thread_branch_callback->Run(nullptr, 0); + } else if(m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + ola::rdm::RunRDMCallback(thread_rdm_callback, ola::rdm::RDM_FAILED_TO_SEND); } sendRDM = false; } else { @@ -290,6 +300,15 @@ void *FtdiDmxThread::Run() { } else { thread_mute_callback->Run(false); } + } else if(m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + + if(readBytes > 0) { + thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_pending_request)); + } else { + RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + } } } else { From b02363ba98acf1099604b344e2b16185d813f25e Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 9 Jan 2019 01:02:41 +0200 Subject: [PATCH 15/86] Set the pending request back to nullptr in the right places and nome more debug output. Works now, but reply is not being read I really need to get another FTDI interface or some other way to monitor the line :/ Also shutdown works again (which may be due to next commit) --- plugins/ftdidmx/FtdiDmxThread.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index e884a786bf..ea3a4f95fe 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -71,8 +71,11 @@ FtdiDmxThread::~FtdiDmxThread() { * @brief Stop this thread */ bool FtdiDmxThread::Stop() { - ola::thread::MutexLocker locker(&m_term_mutex); - m_term = true; + + { + ola::thread::MutexLocker locker(&m_term_mutex); + m_term = true; + } if(m_pending_request != nullptr) { //destroy pending request and callbacks @@ -138,7 +141,7 @@ void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1); } else { // Already pending request - + OLA_WARN << "Unable to queue Mute request, RDM operation already pending"; } } @@ -187,6 +190,7 @@ void *FtdiDmxThread::Run() { UnMuteDeviceCallback *thread_unmute_callback = nullptr; BranchCallback *thread_branch_callback = nullptr; ola::rdm::RDMCallback *thread_rdm_callback = nullptr; + ola::rdm::RDMRequest *thread_pending_request = nullptr; int frameTime = static_cast(floor( @@ -245,6 +249,7 @@ void *FtdiDmxThread::Run() { sendRDM = true; } } else { + OLA_INFO << "NOK to send RDM (DMX interval)"; sendRDM = false; } } else { @@ -279,10 +284,11 @@ void *FtdiDmxThread::Run() { if(m_pending_request->IsDUB()) { usleep(58000); //min time before next packet broadcast allowed readBytes = m_interface->Read(readBuffer, 258); - + OLA_INFO << "DUB Read: " << readBytes; if(m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; + m_pending_request = nullptr; thread_branch_callback->Run(readBuffer, readBytes); } } @@ -296,8 +302,10 @@ void *FtdiDmxThread::Run() { m_mute_complete = nullptr; if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + m_pending_request = nullptr; thread_mute_callback->Run(true); } else { + m_pending_request = nullptr; thread_mute_callback->Run(false); } } else if(m_rdm_callback != nullptr) { @@ -305,8 +313,11 @@ void *FtdiDmxThread::Run() { m_rdm_callback = nullptr; if(readBytes > 0) { - thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), m_pending_request)); + thread_pending_request = m_pending_request; + m_pending_request = nullptr; + thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), thread_pending_request)); } else { + m_pending_request = nullptr; RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); } } @@ -316,10 +327,10 @@ void *FtdiDmxThread::Run() { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; OLA_INFO << "UnMuteAllCallback"; + m_pending_request = nullptr; thread_unmute_callback->Run(); } } - m_pending_request = nullptr; } else { if(m_branch_callback != nullptr) { @@ -327,6 +338,8 @@ void *FtdiDmxThread::Run() { } else if(m_unmute_complete != nullptr) { + } else if(m_rdm_callback != nullptr) { + } } From c87ebf621508a98704ab45b92c40678f5ad054a1 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 10 Jan 2019 18:51:04 +0200 Subject: [PATCH 16/86] Added FtdiInterface::WriteAndRead() in an attempt to rule out context switching messing up the reading of the reply. Still no luck, will need to wait for new FTDI board to read the line. --- plugins/ftdidmx/FtdiDmxThread.cpp | 61 ++++++++++++++++++++++++++++++- plugins/ftdidmx/FtdiWidget.cpp | 29 ++++++++++++++- plugins/ftdidmx/FtdiWidget.h | 3 ++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index ea3a4f95fe..88c132e65b 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -279,7 +279,64 @@ void *FtdiDmxThread::Run() { clock.CurrentTime(&lastDMX); } } else { - if(m_interface->Write(&packetBuffer)) { + if(!m_pending_request->DestinationUID().IsBroadcast() || m_pending_request->IsDUB()) { + if((readBytes = m_interface->WriteAndRead(&packetBuffer, readBuffer, sizeof(readBuffer), (m_pending_request->IsDUB() ? 58000 : 30000))) >= 0) { + if(m_pending_request->IsDUB()) { + if(m_branch_callback != nullptr) { + thread_branch_callback = m_branch_callback; + m_branch_callback = nullptr; + m_pending_request = nullptr; + thread_branch_callback->Run(readBuffer, readBytes); + } else { + if(m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + + if(readBytes > 0 && + rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + m_pending_request = nullptr; + thread_mute_callback->Run(true); + } else { + m_pending_request = nullptr; + thread_mute_callback->Run(false); + } + } else if(m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + + if(readBytes > 0) { + thread_pending_request = m_pending_request; + m_pending_request = nullptr; + thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), thread_pending_request)); + } else { + m_pending_request = nullptr; + RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + } + } + } + } + } else { + // Something went wrong, already reported at hw level but we'll need to handle the callbacks + if(m_branch_callback != nullptr) { + + } else if(m_mute_complete != nullptr) { + + } else if(m_unmute_complete != nullptr) { + + } else if(m_rdm_callback != nullptr) { + } + } + } else if(m_interface->Write(&packetBuffer)) { + if(m_unmute_complete != nullptr) { + thread_unmute_callback = m_unmute_complete; + m_unmute_complete = nullptr; + OLA_INFO << "UnMuteAllCallback"; + m_pending_request = nullptr; + thread_unmute_callback->Run(); + } + } + +/* if(m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet"; if(m_pending_request->IsDUB()) { usleep(58000); //min time before next packet broadcast allowed @@ -341,7 +398,7 @@ void *FtdiDmxThread::Run() { } else if(m_rdm_callback != nullptr) { } - } + } */ goto framesleep; } diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 90e27483a6..33d3b52270 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -383,9 +384,35 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { } } +int FtdiInterface::WriteAndRead(ola::io::ByteString *packet, unsigned char *readBuffer, unsigned long readBufferSize, int minWait) { + int bytesWritten = ftdi_write_data(&m_handle, packet->data(), packet->size()); + int size = packet->size(); + if(bytesWritten < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + return bytesWritten; + } else if (bytesWritten == (int)packet->size()){ + usleep(minWait); + int bytesRead = ftdi_read_data(&m_handle, readBuffer, readBufferSize); + if(bytesRead < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + return bytesRead; + } else { + OLA_INFO << "Read bytes: " << bytesRead; + return bytesRead; + } + + } else { + OLA_WARN << "Bytes Written: " << bytesWritten << " Packet Size: " << size; + return -1; + } +} + int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); - if (read < 0) { + OLA_INFO << "FtdiRead"; + if (read <= 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return read; diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index dbcd46e3e6..90c08175d7 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -230,6 +230,9 @@ class FtdiInterface { /** @brief Write prepared packets to previously opened line, agnostic to packet contents */ bool Write(ola::io::ByteString *packet); + /** @brief Write prepared packet and read line into buffer */ + int WriteAndRead(ola::io::ByteString *packet, unsigned char *readBuffer, long unsigned int size, int minWait); + /** @brief Read data from a previously-opened line */ int Read(unsigned char* buff, int size); From 0141ad0b710364b70a532c2bf579f0dc0514c937 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 18 Jan 2019 00:41:43 +0200 Subject: [PATCH 17/86] 3 Fixes 1. Clear packetbuffer before use. 2. Fix logic of callbacks (else was to wrong if()) 3. Fix packet reconstruction for non-DUB replies: the MAB is recognized as another byte by the FTDI so it reads 1 byte more then the actual packet so we hand of starting 1 byte later and 1 byte less total. --- plugins/ftdidmx/FtdiDmxThread.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 88c132e65b..9bf5827a35 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -220,6 +220,9 @@ void *FtdiDmxThread::Run() { elapsed = ts1 - lastDMX; if(elapsed.InMilliSeconds() < 500) { + if(!packetBuffer.empty()) { + packetBuffer.clear(); + } if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; @@ -287,17 +290,20 @@ void *FtdiDmxThread::Run() { m_branch_callback = nullptr; m_pending_request = nullptr; thread_branch_callback->Run(readBuffer, readBytes); - } else { + } + } else { if(m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; if(readBytes > 0 && - rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { m_pending_request = nullptr; + OLA_INFO << "Mute callback(true)"; thread_mute_callback->Run(true); } else { m_pending_request = nullptr; + OLA_INFO << "Mute callback(false)"; thread_mute_callback->Run(false); } } else if(m_rdm_callback != nullptr) { @@ -307,14 +313,14 @@ void *FtdiDmxThread::Run() { if(readBytes > 0) { thread_pending_request = m_pending_request; m_pending_request = nullptr; - thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), thread_pending_request)); + thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1), thread_pending_request)); } else { m_pending_request = nullptr; RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); } } } - } + } else { // Something went wrong, already reported at hw level but we'll need to handle the callbacks if(m_branch_callback != nullptr) { From 2373f60d320462d4fd4f1166dff980700026ed7d Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 28 Jan 2019 00:25:09 +0200 Subject: [PATCH 18/86] Added single function to handle destruction of any outstanding callbacks. This declutters rest of the code. --- plugins/ftdidmx/FtdiDmxThread.cpp | 59 +++++++++++++++++-------------- plugins/ftdidmx/FtdiDmxThread.h | 5 ++- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 9bf5827a35..5f532dc274 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -131,6 +131,36 @@ void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, } } +/** + * @brief Method called to cleanup any outstanding callbacks + * @param state + * + * All callbacks except the RDMCallback lack a way of reporting an error state to the caller. + */ +void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { + MuteDeviceCallback *thread_mute_callback = nullptr; + UnMuteDeviceCallback *thread_unmute_callback = nullptr; + BranchCallback *thread_branch_callback = nullptr; + ola::rdm::RDMCallback *thread_rdm_callback = nullptr; + + if(m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + thread_mute_callback->Run(false); + } else if(m_unmute_complete != nullptr) { + thread_unmute_callback = m_unmute_complete; + m_unmute_complete = nullptr; + thread_unmute_callback->Run(); + } else if(m_branch_callback != nullptr) { + thread_branch_callback = m_branch_callback; + m_branch_callback = nullptr; + thread_branch_callback->Run(nullptr, 0); + } else if(m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + ola::rdm::RunRDMCallback(thread_rdm_callback, state); + } +} void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { @@ -228,24 +258,7 @@ void *FtdiDmxThread::Run() { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; m_pending_request = nullptr; - // This behavior is wrong, this suggests to whoever is doing the discovery that no devices are connected/responding while we actually just failed to get the packet to the line. - if(m_mute_complete != nullptr) { - thread_mute_callback = m_mute_complete; - m_mute_complete = nullptr; - thread_mute_callback->Run(false); - } else if(m_unmute_complete != nullptr) { - thread_unmute_callback = m_unmute_complete; - m_unmute_complete = nullptr; - thread_unmute_callback->Run(); - } else if(m_branch_callback != nullptr) { - thread_branch_callback = m_branch_callback; - m_branch_callback = nullptr; - thread_branch_callback->Run(nullptr, 0); - } else if(m_rdm_callback != nullptr) { - thread_rdm_callback = m_rdm_callback; - m_rdm_callback = nullptr; - ola::rdm::RunRDMCallback(thread_rdm_callback, ola::rdm::RDM_FAILED_TO_SEND); - } + destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); sendRDM = false; } else { OLA_INFO << "OK To send RDM"; @@ -323,14 +336,8 @@ void *FtdiDmxThread::Run() { } else { // Something went wrong, already reported at hw level but we'll need to handle the callbacks - if(m_branch_callback != nullptr) { - - } else if(m_mute_complete != nullptr) { - - } else if(m_unmute_complete != nullptr) { - - } else if(m_rdm_callback != nullptr) { - } + // Strictly speaking we failed to receive OR send, I have proposed another code: RDM_HW_ERROR + destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); } } else if(m_interface->Write(&packetBuffer)) { if(m_unmute_complete != nullptr) { diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 565f64f044..f0dd45919a 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -89,11 +89,14 @@ class FtdiDmxThread UnMuteDeviceCallback *m_unmute_complete; BranchCallback *m_branch_callback; - void CheckTimeGranularity(); void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool status, const ola::rdm::UIDSet &uids); + void destroyPendindingCallback(ola::rdm::RDMStatusCode state); + + void CheckTimeGranularity(); + static const uint32_t DMX_MAB = 16; static const uint32_t DMX_BREAK = 110; static const uint32_t BAD_GRANULARITY_LIMIT = 3; From 2198e3dacfd5fca9efd15d0cdb93368784a11532 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 28 Jan 2019 01:18:02 +0200 Subject: [PATCH 19/86] Added 'destruction' of callbacks to destructor. It runs them, the pending request should be destroyed by the core that generated it which is why it can be set to null. --- plugins/ftdidmx/FtdiDmxThread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 5f532dc274..4fb915da39 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -78,8 +78,10 @@ bool FtdiDmxThread::Stop() { } if(m_pending_request != nullptr) { - //destroy pending request and callbacks + m_pending_request = nullptr; + destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); } + m_discovery_agent.Abort(); return Join(); } From 65e11d81973b851263dd55ce739c30dd1a49c576 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 25 Feb 2019 23:49:09 +0200 Subject: [PATCH 20/86] Switch back to scheduling with seperate write() and read() functions. Old scheduling logic commented out, will be removed in next commit. --- plugins/ftdidmx/FtdiDmxThread.cpp | 69 ++++++++++++++----------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 4fb915da39..0e883450c9 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -296,7 +296,7 @@ void *FtdiDmxThread::Run() { } else { clock.CurrentTime(&lastDMX); } - } else { + } else {/* if(!m_pending_request->DestinationUID().IsBroadcast() || m_pending_request->IsDUB()) { if((readBytes = m_interface->WriteAndRead(&packetBuffer, readBuffer, sizeof(readBuffer), (m_pending_request->IsDUB() ? 58000 : 30000))) >= 0) { if(m_pending_request->IsDUB()) { @@ -349,10 +349,10 @@ void *FtdiDmxThread::Run() { m_pending_request = nullptr; thread_unmute_callback->Run(); } - } + } // End ReadAndWrite loop */ -/* if(m_interface->Write(&packetBuffer)) { - OLA_INFO << "RDM packet"; + if(m_interface->Write(&packetBuffer)) { + OLA_INFO << "RDM packet written to line"; if(m_pending_request->IsDUB()) { usleep(58000); //min time before next packet broadcast allowed readBytes = m_interface->Read(readBuffer, 258); @@ -361,7 +361,7 @@ void *FtdiDmxThread::Run() { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; m_pending_request = nullptr; - thread_branch_callback->Run(readBuffer, readBytes); + thread_branch_callback->Run(readBuffer, (readBytes >= 0 ? readBytes : 0)); } } else if(!m_pending_request->DestinationUID().IsBroadcast()) { @@ -369,31 +369,32 @@ void *FtdiDmxThread::Run() { usleep(30000); //min time before next packet allowed readBytes = m_interface->Read(readBuffer, 258); - if(m_mute_complete != nullptr) { - thread_mute_callback = m_mute_complete; - m_mute_complete = nullptr; + if(readBytes >=0) { + if(m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; - if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes))->Response()->SourceUID() == m_pending_request->DestinationUID()) { - m_pending_request = nullptr; - thread_mute_callback->Run(true); - } else { - m_pending_request = nullptr; - thread_mute_callback->Run(false); - } - } else if(m_rdm_callback != nullptr) { - thread_rdm_callback = m_rdm_callback; - m_rdm_callback = nullptr; - - if(readBytes > 0) { - thread_pending_request = m_pending_request; - m_pending_request = nullptr; - thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer, readBytes), thread_pending_request)); - } else { - m_pending_request = nullptr; - RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + m_pending_request = nullptr; + thread_mute_callback->Run(true); + } else { + m_pending_request = nullptr; + thread_mute_callback->Run(false); + } + } else if(m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + + if(readBytes > 0) { + thread_pending_request = m_pending_request; + m_pending_request = nullptr; + thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1), thread_pending_request)); + } else { + m_pending_request = nullptr; + RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + } } } - } else { if(m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; @@ -404,16 +405,10 @@ void *FtdiDmxThread::Run() { } } } else { - if(m_branch_callback != nullptr) { - - } else if(m_mute_complete != nullptr) { - - } else if(m_unmute_complete != nullptr) { - - } else if(m_rdm_callback != nullptr) { - - } - } */ + // Something went wrong, already reported at hw level but we'll need to handle the callbacks + // Strictly speaking we failed to receive OR send, I have proposed another code: RDM_HW_ERROR + destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); + } // End of Write loop */ goto framesleep; } From d719f6b5c1d5aae3a3334b16e7fc6a19f2d7c1a3 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 26 Feb 2019 00:30:05 +0200 Subject: [PATCH 21/86] Removal of WriteAndRead() and related scheduler. --- plugins/ftdidmx/FtdiDmxThread.cpp | 56 +------------------------------ plugins/ftdidmx/FtdiWidget.cpp | 25 -------------- plugins/ftdidmx/FtdiWidget.h | 3 -- 3 files changed, 1 insertion(+), 83 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 0e883450c9..978aae6421 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -296,61 +296,7 @@ void *FtdiDmxThread::Run() { } else { clock.CurrentTime(&lastDMX); } - } else {/* - if(!m_pending_request->DestinationUID().IsBroadcast() || m_pending_request->IsDUB()) { - if((readBytes = m_interface->WriteAndRead(&packetBuffer, readBuffer, sizeof(readBuffer), (m_pending_request->IsDUB() ? 58000 : 30000))) >= 0) { - if(m_pending_request->IsDUB()) { - if(m_branch_callback != nullptr) { - thread_branch_callback = m_branch_callback; - m_branch_callback = nullptr; - m_pending_request = nullptr; - thread_branch_callback->Run(readBuffer, readBytes); - } - } else { - if(m_mute_complete != nullptr) { - thread_mute_callback = m_mute_complete; - m_mute_complete = nullptr; - - if(readBytes > 0 && - rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { - m_pending_request = nullptr; - OLA_INFO << "Mute callback(true)"; - thread_mute_callback->Run(true); - } else { - m_pending_request = nullptr; - OLA_INFO << "Mute callback(false)"; - thread_mute_callback->Run(false); - } - } else if(m_rdm_callback != nullptr) { - thread_rdm_callback = m_rdm_callback; - m_rdm_callback = nullptr; - - if(readBytes > 0) { - thread_pending_request = m_pending_request; - m_pending_request = nullptr; - thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1), thread_pending_request)); - } else { - m_pending_request = nullptr; - RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); - } - } - } - - } else { - // Something went wrong, already reported at hw level but we'll need to handle the callbacks - // Strictly speaking we failed to receive OR send, I have proposed another code: RDM_HW_ERROR - destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); - } - } else if(m_interface->Write(&packetBuffer)) { - if(m_unmute_complete != nullptr) { - thread_unmute_callback = m_unmute_complete; - m_unmute_complete = nullptr; - OLA_INFO << "UnMuteAllCallback"; - m_pending_request = nullptr; - thread_unmute_callback->Run(); - } - } // End ReadAndWrite loop */ - + } else { if(m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; if(m_pending_request->IsDUB()) { diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 33d3b52270..b0cc8fa1ce 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -384,31 +384,6 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { } } -int FtdiInterface::WriteAndRead(ola::io::ByteString *packet, unsigned char *readBuffer, unsigned long readBufferSize, int minWait) { - int bytesWritten = ftdi_write_data(&m_handle, packet->data(), packet->size()); - int size = packet->size(); - if(bytesWritten < 0) { - OLA_WARN << m_parent->Description() << " " - << ftdi_get_error_string(&m_handle); - return bytesWritten; - } else if (bytesWritten == (int)packet->size()){ - usleep(minWait); - int bytesRead = ftdi_read_data(&m_handle, readBuffer, readBufferSize); - if(bytesRead < 0) { - OLA_WARN << m_parent->Description() << " " - << ftdi_get_error_string(&m_handle); - return bytesRead; - } else { - OLA_INFO << "Read bytes: " << bytesRead; - return bytesRead; - } - - } else { - OLA_WARN << "Bytes Written: " << bytesWritten << " Packet Size: " << size; - return -1; - } -} - int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); OLA_INFO << "FtdiRead"; diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 90c08175d7..dbcd46e3e6 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -230,9 +230,6 @@ class FtdiInterface { /** @brief Write prepared packets to previously opened line, agnostic to packet contents */ bool Write(ola::io::ByteString *packet); - /** @brief Write prepared packet and read line into buffer */ - int WriteAndRead(ola::io::ByteString *packet, unsigned char *readBuffer, long unsigned int size, int minWait); - /** @brief Read data from a previously-opened line */ int Read(unsigned char* buff, int size); From a0e6cb4f94c6efd76dda385b0a88abfad84bc300 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 26 Feb 2019 22:59:56 +0200 Subject: [PATCH 22/86] Fix for part of comments by PeterNewman in PR1541. --- plugins/ftdidmx/FtdiDmxPort.h | 3 +-- plugins/ftdidmx/FtdiDmxThread.cpp | 24 ++++++++++++++---------- plugins/ftdidmx/FtdiDmxThread.h | 6 ++++++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 65b888fbe0..5659d3e5b4 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -43,8 +43,7 @@ namespace ola { namespace plugin { namespace ftdidmx { -class FtdiDmxOutputPort - : public ola::BasicOutputPort { +class FtdiDmxOutputPort : public ola::BasicOutputPort { public: FtdiDmxOutputPort(FtdiDmxDevice *parent, FtdiInterface *interface, diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 978aae6421..0f416aef99 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -98,7 +98,7 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { } void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, - ola::rdm::RDMCallback *callback) { + ola::rdm::RDMCallback *callback) { ola::thread::MutexLocker locker(&m_rdm_mutex); if(m_pending_request == nullptr) { m_pending_request = request; @@ -125,9 +125,13 @@ void FtdiDmxThread::RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *call * @param uids the UIDSet of UIDs that were found. */ void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, - bool, - const ola::rdm::UIDSet &uids) { - OLA_DEBUG << "FTDI discovery complete: " << uids; + bool status, + const ola::rdm::UIDSet &uids) { + if(status) { + OLA_DEBUG << "FTDI discovery complete: " << uids; + } else { + OLA_WARN << "FTDI discovery failed"; + } if (callback) { callback->Run(uids); } @@ -172,7 +176,7 @@ void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, m_mute_complete = mute_complete; m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1); } else { - // Already pending request + // Already pending request OLA_WARN << "Unable to queue Mute request, RDM operation already pending"; } } @@ -251,7 +255,7 @@ void *FtdiDmxThread::Run() { elapsed = ts1 - lastDMX; - if(elapsed.InMilliSeconds() < 500) { + if(elapsed.InMilliSeconds() < HALF_SECOND_MS) { if(!packetBuffer.empty()) { packetBuffer.clear(); } @@ -300,8 +304,8 @@ void *FtdiDmxThread::Run() { if(m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; if(m_pending_request->IsDUB()) { - usleep(58000); //min time before next packet broadcast allowed - readBytes = m_interface->Read(readBuffer, 258); + usleep(MIN_WAIT_DUB_US); //min time before next packet broadcast allowed + readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); OLA_INFO << "DUB Read: " << readBytes; if(m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; @@ -312,8 +316,8 @@ void *FtdiDmxThread::Run() { } else if(!m_pending_request->DestinationUID().IsBroadcast()) { - usleep(30000); //min time before next packet allowed - readBytes = m_interface->Read(readBuffer, 258); + usleep(MIN_WAIT_RDM_US); //min time before next packet allowed + readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); if(readBytes >=0) { if(m_mute_complete != nullptr) { diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index f0dd45919a..61af3bee70 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -39,6 +39,12 @@ namespace ola { namespace plugin { namespace ftdidmx { +enum { + HALF_SECOND_MS = 500, + MIN_WAIT_DUB_US = 58000, + MIN_WAIT_RDM_US = 30000, +}; + class FtdiDmxThread : public ola::thread::Thread, public ola::rdm::DiscoverableRDMControllerInterface, From 0ba5dfde167a5c2731ac03cb21c1a9c9db92f98d Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 26 Feb 2019 23:30:20 +0200 Subject: [PATCH 23/86] Fix part of travis lint issues. 80 character limit is big issue. --- plugins/ftdidmx/FtdiDmxPort.h | 3 +- plugins/ftdidmx/FtdiDmxThread.cpp | 93 +++++++++++++++++++------------ plugins/ftdidmx/FtdiWidget.cpp | 4 +- plugins/ftdidmx/FtdiWidget.h | 3 +- 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 5659d3e5b4..afadfcf014 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -77,10 +77,9 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { std::string Description() const { return m_interface->Description(); } - private: + private: FtdiInterface *m_interface; FtdiDmxThread m_thread; - }; } // namespace ftdidmx } // namespace plugin diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 0f416aef99..8cc6151f00 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -71,13 +71,12 @@ FtdiDmxThread::~FtdiDmxThread() { * @brief Stop this thread */ bool FtdiDmxThread::Stop() { - { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } - if(m_pending_request != nullptr) { + if (m_pending_request != nullptr) { m_pending_request = nullptr; destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); } @@ -100,21 +99,26 @@ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { ola::thread::MutexLocker locker(&m_rdm_mutex); - if(m_pending_request == nullptr) { + if (m_pending_request == nullptr) { m_pending_request = request; m_rdm_callback = callback; } else { OLA_WARN << "Unable to queue RDM request, RDM operation already pending"; } - OLA_WARN << "Function not properly implemented yet, callback may not get called."; } void FtdiDmxThread::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { - m_discovery_agent.StartFullDiscovery(ola::NewSingleCallback(this, &FtdiDmxThread::DiscoveryComplete, callback)); + m_discovery_agent.StartFullDiscovery( + ola::NewSingleCallback(this, + &FtdiDmxThread::DiscoveryComplete, + callback)); } void FtdiDmxThread::RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { - m_discovery_agent.StartIncrementalDiscovery(ola::NewSingleCallback(this, &FtdiDmxThread::DiscoveryComplete, callback)); + m_discovery_agent.StartIncrementalDiscovery( + ola::NewSingleCallback(this, + &FtdiDmxThread::DiscoveryComplete, + callback)); } /** @@ -127,7 +131,7 @@ void FtdiDmxThread::RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *call void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool status, const ola::rdm::UIDSet &uids) { - if(status) { + if (status) { OLA_DEBUG << "FTDI discovery complete: " << uids; } else { OLA_WARN << "FTDI discovery failed"; @@ -141,7 +145,8 @@ void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, * @brief Method called to cleanup any outstanding callbacks * @param state * - * All callbacks except the RDMCallback lack a way of reporting an error state to the caller. + * All callbacks except the RDMCallback lack a way of reporting an error state + * to the caller. */ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { MuteDeviceCallback *thread_mute_callback = nullptr; @@ -149,19 +154,19 @@ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { BranchCallback *thread_branch_callback = nullptr; ola::rdm::RDMCallback *thread_rdm_callback = nullptr; - if(m_mute_complete != nullptr) { + if (m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; thread_mute_callback->Run(false); - } else if(m_unmute_complete != nullptr) { + } else if (m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; thread_unmute_callback->Run(); - } else if(m_branch_callback != nullptr) { + } else if (m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; thread_branch_callback->Run(nullptr, 0); - } else if(m_rdm_callback != nullptr) { + } else if (m_rdm_callback != nullptr) { thread_rdm_callback = m_rdm_callback; m_rdm_callback = nullptr; ola::rdm::RunRDMCallback(thread_rdm_callback, state); @@ -171,25 +176,31 @@ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { ola::thread::MutexLocker locker(&m_rdm_mutex); - if(m_pending_request == nullptr) { + if (m_pending_request == nullptr) { OLA_INFO << "Muting device"; m_mute_complete = mute_complete; - m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number += 1); + m_pending_request = ola::rdm::NewMuteRequest(m_uid, + target, + m_transaction_number += 1); } else { // Already pending request - OLA_WARN << "Unable to queue Mute request, RDM operation already pending"; + OLA_WARN << "Unable to queue Mute request, " + << "RDM operation already pending"; } } void FtdiDmxThread::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { ola::thread::MutexLocker locker(&m_rdm_mutex); - if(m_pending_request == nullptr) { + if (m_pending_request == nullptr) { OLA_INFO << "Sending UnMuteAll"; m_unmute_complete = unmute_complete; - m_pending_request = ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number += 1); + m_pending_request = ola::rdm::NewUnMuteRequest(m_uid, + ola::rdm::UID::AllDevices(), + m_transaction_number += 1); } else { - // Already pending request - OLA_WARN << "Unable to queue UnMuteAll request, RDM operation already pending"; + // Already pending request + OLA_WARN << "Unable to queue UnMuteAll request, " + << "RDM operation already pending"; } } @@ -197,13 +208,18 @@ void FtdiDmxThread::Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { ola::thread::MutexLocker locker(&m_rdm_mutex); - if(m_pending_request == nullptr) { + if (m_pending_request == nullptr) { OLA_INFO << "Sending branch"; m_branch_callback = callback; - m_pending_request = ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number += 1); + m_pending_request = + ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, + lower, + upper, + m_transaction_number += 1); } else { - // Already pending request - OLA_WARN << "Unable to queue Branch request, RDM operation already pending"; + // Already pending request + OLA_WARN << "Unable to queue Branch request, " + << "RDM operation already pending"; } } @@ -251,16 +267,16 @@ void *FtdiDmxThread::Run() { } clock.CurrentTime(&ts1); - if(m_pending_request != nullptr) { + if (m_pending_request != nullptr) { elapsed = ts1 - lastDMX; - if(elapsed.InMilliSeconds() < HALF_SECOND_MS) { - if(!packetBuffer.empty()) { + if (elapsed.InMilliSeconds() < HALF_SECOND_MS) { + if (!packetBuffer.empty()) { packetBuffer.clear(); } - if(!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { + if (!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; m_pending_request = nullptr; @@ -294,27 +310,27 @@ void *FtdiDmxThread::Run() { usleep(DMX_MAB); } - if(!sendRDM) { + if (!sendRDM) { if (!m_interface->Write(buffer)) { goto framesleep; } else { clock.CurrentTime(&lastDMX); } } else { - if(m_interface->Write(&packetBuffer)) { + if (m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; - if(m_pending_request->IsDUB()) { + if (m_pending_request->IsDUB()) { usleep(MIN_WAIT_DUB_US); //min time before next packet broadcast allowed readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); OLA_INFO << "DUB Read: " << readBytes; - if(m_branch_callback != nullptr) { + if (m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; m_pending_request = nullptr; thread_branch_callback->Run(readBuffer, (readBytes >= 0 ? readBytes : 0)); } } - else if(!m_pending_request->DestinationUID().IsBroadcast()) { + else if (!m_pending_request->DestinationUID().IsBroadcast()) { usleep(MIN_WAIT_RDM_US); //min time before next packet allowed readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); @@ -324,21 +340,24 @@ void *FtdiDmxThread::Run() { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; - if(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { + if (rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { m_pending_request = nullptr; thread_mute_callback->Run(true); } else { m_pending_request = nullptr; thread_mute_callback->Run(false); } - } else if(m_rdm_callback != nullptr) { + } else if (m_rdm_callback != nullptr) { thread_rdm_callback = m_rdm_callback; m_rdm_callback = nullptr; - if(readBytes > 0) { + if (readBytes > 0) { thread_pending_request = m_pending_request; m_pending_request = nullptr; - thread_rdm_callback->Run(rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1), thread_pending_request)); + thread_rdm_callback->Run(rdm::RDMReply::FromFrame( + rdm::RDMFrame(readBuffer+1, + readBytes-1), + thread_pending_request)); } else { m_pending_request = nullptr; RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); @@ -346,7 +365,7 @@ void *FtdiDmxThread::Run() { } } } else { - if(m_unmute_complete != nullptr) { + if (m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; OLA_INFO << "UnMuteAllCallback"; diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index b0cc8fa1ce..0cfb0c179f 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -372,11 +372,11 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { bool FtdiInterface::Write(ola::io::ByteString *packet) { int bytesWritten = ftdi_write_data(&m_handle, packet->data(), packet->size()); int size = packet->size(); - if(bytesWritten < 0) { + if (bytesWritten < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; - } else if (bytesWritten == (int)packet->size()){ + } else if (bytesWritten == static_cast(packet->size())) { return true; } else { OLA_WARN << "Bytes Written: " << bytesWritten << " Packet Size: " << size; diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index dbcd46e3e6..25e2e2d314 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -227,7 +227,8 @@ class FtdiInterface { /** @brief Write data to a previously-opened line, DMX only */ bool Write(const ola::DmxBuffer &data); - /** @brief Write prepared packets to previously opened line, agnostic to packet contents */ + /** @brief Write prepared packets to previously opened line, + * agnostic to packet contents */ bool Write(ola::io::ByteString *packet); /** @brief Read data from a previously-opened line */ From 29b32d0a2bb5549d597aa59c0cb205ab01fcbc8d Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 26 Feb 2019 23:37:20 +0200 Subject: [PATCH 24/86] Added section about RDM support to README. --- plugins/ftdidmx/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index b0ce125a37..c40de5425c 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -5,6 +5,16 @@ This plugin is compatible with Enttec OpenDmx and other FTDI chipset based USB to DMX converters where the host needs to create the DMX stream itself and not the interface (the interface has no microprocessor to do so). +RDM Support +=========== + +FTDI based chips/outputs that have the correct line biasing setup should be +able to output and receive RDM packets. + +At this stage not all timings are correct. + +RDM was tested with: +- FT4232H (USB-COM485-PLUS4) ## Config file: ola-ftdidmx.conf From f451f19eba88b6f6722fc0956556b0088c422a75 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 27 Feb 2019 02:16:24 +0200 Subject: [PATCH 25/86] Change for compiler error suggested by Peter, currently not next to interface to check it, but Peter reported it works. --- plugins/ftdidmx/FtdiWidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 0cfb0c179f..6096090140 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -370,7 +370,9 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { bool FtdiInterface::Write(ola::io::ByteString *packet) { - int bytesWritten = ftdi_write_data(&m_handle, packet->data(), packet->size()); + int bytesWritten = ftdi_write_data(&m_handle, + const_cast(packet->data()), + packet->size()); int size = packet->size(); if (bytesWritten < 0) { OLA_WARN << m_parent->Description() << " " From abdf4d5049093574db25964ae11e3445b580f4ad Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 28 Feb 2019 02:50:42 +0200 Subject: [PATCH 26/86] Switch to using serial from FTDI device as serial part in RDM UID. Also some fixes to automated checks complaints. --- plugins/ftdidmx/FtdiDmxDevice.cpp | 9 ++++++++- plugins/ftdidmx/FtdiDmxPort.h | 5 +++-- plugins/ftdidmx/FtdiDmxThread.cpp | 30 ++++++++++++++++-------------- plugins/ftdidmx/FtdiDmxThread.h | 4 +++- plugins/ftdidmx/FtdiWidget.cpp | 4 ++++ plugins/ftdidmx/README.md | 4 ++-- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxDevice.cpp b/plugins/ftdidmx/FtdiDmxDevice.cpp index ed77711a10..75debb8086 100644 --- a/plugins/ftdidmx/FtdiDmxDevice.cpp +++ b/plugins/ftdidmx/FtdiDmxDevice.cpp @@ -54,6 +54,7 @@ FtdiDmxDevice::~FtdiDmxDevice() { } bool FtdiDmxDevice::StartHook() { + char *end; unsigned int interface_count = m_widget->GetInterfaceCount(); unsigned int successfully_added = 0; @@ -64,7 +65,13 @@ bool FtdiDmxDevice::StartHook() { FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); if (port->SetupOutput()) { - AddPort(new FtdiDmxOutputPort(this, port, i, m_frequency)); + AddPort(new FtdiDmxOutputPort(this, + port, + i, + m_frequency, + static_cast(strtol(m_widget->Serial().c_str(), + &end, + 36)))); successfully_added += 1; } else { OLA_WARN << "Failed to add interface: " << i; diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index afadfcf014..4496c9c59b 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -48,10 +48,11 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { FtdiDmxOutputPort(FtdiDmxDevice *parent, FtdiInterface *interface, unsigned int id, - unsigned int freq) + unsigned int freq, + unsigned int serial) : BasicOutputPort(parent, id, false, true), m_interface(interface), - m_thread(interface, freq) { + m_thread(interface, freq, serial) { m_thread.Start(); } ~FtdiDmxOutputPort() { diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 8cc6151f00..be1471c09b 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -47,14 +47,16 @@ namespace ola { namespace plugin { namespace ftdidmx { -FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency) +FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, + unsigned int frequency, + unsigned int serial) : m_granularity(UNKNOWN), m_interface(interface), m_term(false), m_frequency(frequency), m_transaction_number(0), m_discovery_agent(this), - m_uid(0x7a70, 0x12345678), + m_uid(0x7a70, serial), m_pending_request(nullptr), m_rdm_callback(nullptr), m_mute_complete(nullptr), @@ -268,7 +270,6 @@ void *FtdiDmxThread::Run() { clock.CurrentTime(&ts1); if (m_pending_request != nullptr) { - elapsed = ts1 - lastDMX; if (elapsed.InMilliSeconds() < HALF_SECOND_MS) { @@ -320,23 +321,23 @@ void *FtdiDmxThread::Run() { if (m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; if (m_pending_request->IsDUB()) { - usleep(MIN_WAIT_DUB_US); //min time before next packet broadcast allowed + usleep(MIN_WAIT_DUB_US); + readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); OLA_INFO << "DUB Read: " << readBytes; if (m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; m_pending_request = nullptr; - thread_branch_callback->Run(readBuffer, (readBytes >= 0 ? readBytes : 0)); + thread_branch_callback->Run(readBuffer, + (readBytes >= 0 ? readBytes : 0)); } - } - else if (!m_pending_request->DestinationUID().IsBroadcast()) { - - usleep(MIN_WAIT_RDM_US); //min time before next packet allowed + } else if (!m_pending_request->DestinationUID().IsBroadcast()) { + usleep(MIN_WAIT_RDM_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); - if(readBytes >=0) { - if(m_mute_complete != nullptr) { + if (readBytes >= 0) { + if (m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; @@ -363,7 +364,7 @@ void *FtdiDmxThread::Run() { RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); } } - } + } else {/* TODO: run some type of timeout */} } else { if (m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; @@ -374,8 +375,9 @@ void *FtdiDmxThread::Run() { } } } else { - // Something went wrong, already reported at hw level but we'll need to handle the callbacks - // Strictly speaking we failed to receive OR send, I have proposed another code: RDM_HW_ERROR + /* Something went wrong, already reported at hw level + * but we'll need to handle the callbacks. + */ destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); } // End of Write loop */ diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 61af3bee70..8916b2ff89 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -50,7 +50,9 @@ class FtdiDmxThread public ola::rdm::DiscoverableRDMControllerInterface, public ola::rdm::DiscoveryTargetInterface { public: - FtdiDmxThread(FtdiInterface *interface, unsigned int frequency); + FtdiDmxThread(FtdiInterface *interface, + unsigned int frequency, + unsigned int serial); ~FtdiDmxThread(); bool Stop(); diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 6096090140..567ee2d8c3 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -190,6 +190,10 @@ void FtdiWidget::Widgets(vector *widgets) { } } + /* TODO: Serial part of UID for RDM relies on serial, + * need to add a default serial + */ + OLA_INFO << "Found FTDI device. Vendor: '" << v << "', Name: '" << sname << "', Serial: '" << sserial << "'"; ToUpper(&v); diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index c40de5425c..ed5794babf 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -6,7 +6,7 @@ USB to DMX converters where the host needs to create the DMX stream itself and not the interface (the interface has no microprocessor to do so). RDM Support -=========== +----------- FTDI based chips/outputs that have the correct line biasing setup should be able to output and receive RDM packets. @@ -14,7 +14,7 @@ able to output and receive RDM packets. At this stage not all timings are correct. RDM was tested with: -- FT4232H (USB-COM485-PLUS4) + - FT4232H (USB-COM485-PLUS4) ## Config file: ola-ftdidmx.conf From b080a84fb7d7c14e8166907a667d20e3b341f584 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 28 Feb 2019 15:41:17 +0200 Subject: [PATCH 27/86] Switched to using constant defined in header for Vendor part of UID. Also minor fix of lint issue. --- plugins/ftdidmx/FtdiDmxThread.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index be1471c09b..cc340fea65 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -33,6 +33,7 @@ #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/StringUtils.h" +#include "ola/Constants.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" @@ -56,7 +57,7 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, m_frequency(frequency), m_transaction_number(0), m_discovery_agent(this), - m_uid(0x7a70, serial), + m_uid(OPEN_LIGHTING_ESTA_CODE, serial), m_pending_request(nullptr), m_rdm_callback(nullptr), m_mute_complete(nullptr), @@ -68,7 +69,6 @@ FtdiDmxThread::~FtdiDmxThread() { Stop(); } - /** * @brief Stop this thread */ @@ -379,7 +379,7 @@ void *FtdiDmxThread::Run() { * but we'll need to handle the callbacks. */ destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); - } // End of Write loop */ + } // End of Write loop */ goto framesleep; } From 9874f6db9faf49d9598d8f1d536e6fe0b22e765b Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 4 Mar 2019 00:59:46 +0200 Subject: [PATCH 28/86] Added logic to handle slow replies and make sure a full frame is received or timeout This should meet the timing specs more closely though it can severly harm responsiveness during shows. Also reformatted some lines to fit the 80 char limit. TODO: run through valgrind to check for leaky memory. --- plugins/ftdidmx/FtdiDmxThread.cpp | 117 +++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index cc340fea65..a6c2636c54 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -156,6 +156,7 @@ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { BranchCallback *thread_branch_callback = nullptr; ola::rdm::RDMCallback *thread_rdm_callback = nullptr; + m_pending_request = nullptr; if (m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; @@ -237,6 +238,7 @@ void *FtdiDmxThread::Run() { bool sendRDM = false; TimeInterval elapsed, interval; int readBytes; + unsigned int additionalWait = 0; unsigned char readBuffer[258]; ola::io::ByteString packetBuffer; @@ -244,8 +246,8 @@ void *FtdiDmxThread::Run() { UnMuteDeviceCallback *thread_unmute_callback = nullptr; BranchCallback *thread_branch_callback = nullptr; ola::rdm::RDMCallback *thread_rdm_callback = nullptr; - ola::rdm::RDMRequest *thread_pending_request = nullptr; + ola::rdm::RDMReply *received_reply = nullptr; int frameTime = static_cast(floor( (static_cast(1000) / m_frequency) + static_cast(0.5))); @@ -277,13 +279,20 @@ void *FtdiDmxThread::Run() { packetBuffer.clear(); } - if (!ola::rdm::RDMCommandSerializer::PackWithStartCode(*m_pending_request, &packetBuffer)) { + if (!ola::rdm::RDMCommandSerializer::PackWithStartCode( + *m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; m_pending_request = nullptr; destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); sendRDM = false; } else { + /* Reset reply buffer. + * TODO: make sure no memory is leaked here. + */ + if (received_reply != nullptr) { + received_reply = nullptr; + } OLA_INFO << "OK To send RDM"; sendRDM = true; } @@ -336,35 +345,87 @@ void *FtdiDmxThread::Run() { usleep(MIN_WAIT_RDM_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); - if (readBytes >= 0) { - if (m_mute_complete != nullptr) { - thread_mute_callback = m_mute_complete; - m_mute_complete = nullptr; - - if (rdm::RDMReply::FromFrame(rdm::RDMFrame(readBuffer+1, readBytes-1))->Response()->SourceUID() == m_pending_request->DestinationUID()) { - m_pending_request = nullptr; - thread_mute_callback->Run(true); - } else { - m_pending_request = nullptr; - thread_mute_callback->Run(false); - } - } else if (m_rdm_callback != nullptr) { - thread_rdm_callback = m_rdm_callback; - m_rdm_callback = nullptr; - - if (readBytes > 0) { - thread_pending_request = m_pending_request; - m_pending_request = nullptr; - thread_rdm_callback->Run(rdm::RDMReply::FromFrame( - rdm::RDMFrame(readBuffer+1, - readBytes-1), - thread_pending_request)); + if (readBytes > 0) { + /* + * The following section of code tries to deal with replies that + * are being broadcast too slowly, I don't have equipment that + * malfunctions in this way so I have no way of testing this. + */ + if (readBytes < 4) { + OLA_WARN << "FTDI Didn't receive at least 4B during minWait"; + additionalWait = (MIN_WAIT_RDM_US / readBytes)*(4 - readBytes); + usleep(additionalWait); + readBytes += m_interface->Read(readBuffer+readBytes, + sizeof(readBuffer-readBytes)); + } + /* + * This section of code does minimal verification of the received + * frame. + * This assumes that the 4th byte in the buffer is the 3rd byte of + * the RDM Frame which defines length and no checksum has been done + * yet. + */ + if (readBytes >= 4) { + if (readBuffer[0] == 0x00 && readBuffer[1] == 0xcc) { + while (((readBytes - 1) < readBuffer[3]) && + elapsed.InMilliSeconds() <= 1250) { + OLA_WARN << "FTDI Didn't receive full frame during minWait"; + additionalWait = (MIN_WAIT_RDM_US / readBytes) * + (readBuffer[3] - readBytes + 1); + usleep(additionalWait); + readBytes += m_interface->Read(readBuffer+readBytes, + sizeof(readBuffer-readBytes)); + + clock.CurrentTime(&ts2); + elapsed = ts2 - ts1; + } + if (readBytes < (readBuffer[3] + 1)) { + OLA_WARN << "Discarding due to timeout."; + destroyPendindingCallback(rdm::RDM_TIMEOUT); + } else { + received_reply = rdm::RDMReply::FromFrame( + rdm::RDMFrame(readBuffer+1,readBytes-1), + m_pending_request); + + if(received_reply != nullptr) { + if (m_mute_complete != nullptr) { + thread_mute_callback = m_mute_complete; + m_mute_complete = nullptr; + + if (received_reply->Response()->SourceUID() == + m_pending_request->DestinationUID()) { + m_pending_request = nullptr; + thread_mute_callback->Run(true); + } else { + m_pending_request = nullptr; + thread_mute_callback->Run(false); + } + } else if (m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + + if (readBytes > 0) { + m_pending_request = nullptr; + thread_rdm_callback->Run(received_reply); + } else { + m_pending_request = nullptr; + RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + } + } + } else { + OLA_WARN << "received reply is nullptr"; + destroyPendindingCallback(rdm::RDM_INVALID_RESPONSE); + } + } // End handling seemingly valid data } else { - m_pending_request = nullptr; - RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); + destroyPendindingCallback(rdm::RDM_INVALID_RESPONSE); } + } else { + destroyPendindingCallback(rdm::RDM_TIMEOUT); } - } else {/* TODO: run some type of timeout */} + } else { + destroyPendindingCallback(rdm::RDM_TIMEOUT); + } } else { if (m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; From ab0e96125a70210c17c60e85e3bd27f43839583e Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 4 Mar 2019 01:05:52 +0200 Subject: [PATCH 29/86] Changed from OLA.* to *.extensions used by QtCreator at request of @PeterNewman --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cbd33cb6ff..3633d3898c 100644 --- a/.gitignore +++ b/.gitignore @@ -246,4 +246,7 @@ javascript/new-src/node_modules .cproject .settings .vscode/ -OLA.* +*.config +*.creator* +*.files +*.includes From 4b72f701e57083f415bf9659e02112d069aaf638 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 4 Mar 2019 01:13:48 +0200 Subject: [PATCH 30/86] Fix embarrasing mistake with calculation inside sizeof() --- plugins/ftdidmx/FtdiDmxThread.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index a6c2636c54..a1c3503c1f 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -355,8 +355,8 @@ void *FtdiDmxThread::Run() { OLA_WARN << "FTDI Didn't receive at least 4B during minWait"; additionalWait = (MIN_WAIT_RDM_US / readBytes)*(4 - readBytes); usleep(additionalWait); - readBytes += m_interface->Read(readBuffer+readBytes, - sizeof(readBuffer-readBytes)); + readBytes += m_interface->Read(readBuffer + readBytes, + sizeof(readBuffer) - readBytes); } /* * This section of code does minimal verification of the received @@ -373,8 +373,9 @@ void *FtdiDmxThread::Run() { additionalWait = (MIN_WAIT_RDM_US / readBytes) * (readBuffer[3] - readBytes + 1); usleep(additionalWait); - readBytes += m_interface->Read(readBuffer+readBytes, - sizeof(readBuffer-readBytes)); + readBytes += m_interface->Read( + readBuffer + readBytes, + sizeof(readBuffer) - readBytes); clock.CurrentTime(&ts2); elapsed = ts2 - ts1; From 17a40b1250504c26a9363e941483b893a0bb6dde Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 4 Mar 2019 02:14:40 +0200 Subject: [PATCH 31/86] Fix Travis lint issues. --- plugins/ftdidmx/FtdiDmxDevice.cpp | 16 +++++++++------- plugins/ftdidmx/FtdiDmxThread.cpp | 8 ++++---- plugins/ftdidmx/FtdiDmxThread.h | 2 +- plugins/ftdidmx/FtdiWidget.cpp | 8 +++++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxDevice.cpp b/plugins/ftdidmx/FtdiDmxDevice.cpp index 75debb8086..8a6c728fb2 100644 --- a/plugins/ftdidmx/FtdiDmxDevice.cpp +++ b/plugins/ftdidmx/FtdiDmxDevice.cpp @@ -65,13 +65,15 @@ bool FtdiDmxDevice::StartHook() { FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); if (port->SetupOutput()) { - AddPort(new FtdiDmxOutputPort(this, - port, - i, - m_frequency, - static_cast(strtol(m_widget->Serial().c_str(), - &end, - 36)))); + AddPort(new FtdiDmxOutputPort( + this, + port, + i, + m_frequency, + static_cast(strtol( + m_widget->Serial().c_str(), + &end, + 36)))); successfully_added += 1; } else { OLA_WARN << "Failed to add interface: " << i; diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index a1c3503c1f..d567bff412 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -116,11 +116,11 @@ void FtdiDmxThread::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { callback)); } -void FtdiDmxThread::RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { +void FtdiDmxThread::RunIncrementalDiscovery(rdm::RDMDiscoveryCallback *cb) { m_discovery_agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &FtdiDmxThread::DiscoveryComplete, - callback)); + cb)); } /** @@ -385,10 +385,10 @@ void *FtdiDmxThread::Run() { destroyPendindingCallback(rdm::RDM_TIMEOUT); } else { received_reply = rdm::RDMReply::FromFrame( - rdm::RDMFrame(readBuffer+1,readBytes-1), + rdm::RDMFrame(readBuffer+1, readBytes-1), m_pending_request); - if(received_reply != nullptr) { + if (received_reply != nullptr) { if (m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 8916b2ff89..ff4475c0b2 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -62,7 +62,7 @@ class FtdiDmxThread ola::rdm::RDMCallback *callback); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); - void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); + void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *cb); void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete); diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 567ee2d8c3..4c784fc0d9 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -374,9 +374,11 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { bool FtdiInterface::Write(ola::io::ByteString *packet) { - int bytesWritten = ftdi_write_data(&m_handle, - const_cast(packet->data()), - packet->size()); + int bytesWritten = ftdi_write_data( + &m_handle, + const_cast(packet->data()), + packet->size()); + int size = packet->size(); if (bytesWritten < 0) { OLA_WARN << m_parent->Description() << " " From 532c8c3b1b407aad63f74d2596de05906261fea4 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 5 Mar 2019 00:29:54 +0200 Subject: [PATCH 32/86] Fix memory leak. There are multiple memory leaks in the callback handling or OLA core that need to be handled in the future. --- plugins/ftdidmx/FtdiDmxThread.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index d567bff412..95ae283dc8 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -287,12 +287,6 @@ void *FtdiDmxThread::Run() { destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); sendRDM = false; } else { - /* Reset reply buffer. - * TODO: make sure no memory is leaked here. - */ - if (received_reply != nullptr) { - received_reply = nullptr; - } OLA_INFO << "OK To send RDM"; sendRDM = true; } @@ -417,6 +411,12 @@ void *FtdiDmxThread::Run() { OLA_WARN << "received reply is nullptr"; destroyPendindingCallback(rdm::RDM_INVALID_RESPONSE); } + // Reset reply buffer. + if (received_reply != nullptr) { + rdm::RDMReply *tmp = received_reply; + received_reply = nullptr; + delete tmp; + } } // End handling seemingly valid data } else { destroyPendindingCallback(rdm::RDM_INVALID_RESPONSE); From d28d3df37be359d4e22ff48b6416e77995440799 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 6 Mar 2019 14:55:22 +0200 Subject: [PATCH 33/86] Fix more memory leaks. --- plugins/ftdidmx/FtdiDmxThread.cpp | 25 ++++++++++++++++--------- plugins/ftdidmx/FtdiDmxThread.h | 1 + 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 95ae283dc8..0f8c8b3543 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -79,7 +79,7 @@ bool FtdiDmxThread::Stop() { } if (m_pending_request != nullptr) { - m_pending_request = nullptr; + destroyPendingRequest(); destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); } m_discovery_agent.Abort(); @@ -156,7 +156,8 @@ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { BranchCallback *thread_branch_callback = nullptr; ola::rdm::RDMCallback *thread_rdm_callback = nullptr; - m_pending_request = nullptr; + destroyPendingRequest(); + if (m_mute_complete != nullptr) { thread_mute_callback = m_mute_complete; m_mute_complete = nullptr; @@ -176,6 +177,13 @@ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { } } +void FtdiDmxThread::destroyPendingRequest() { + ola::rdm::RDMRequest *tmp_rdm_request = m_pending_request; + + m_pending_request = nullptr; + delete tmp_rdm_request; +} + void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { ola::thread::MutexLocker locker(&m_rdm_mutex); @@ -282,7 +290,6 @@ void *FtdiDmxThread::Run() { if (!ola::rdm::RDMCommandSerializer::PackWithStartCode( *m_pending_request, &packetBuffer)) { OLA_WARN << "RDMCommandSerializer failed. Dropping packet."; - m_pending_request = nullptr; destroyPendindingCallback(ola::rdm::RDM_FAILED_TO_SEND); sendRDM = false; @@ -331,7 +338,7 @@ void *FtdiDmxThread::Run() { if (m_branch_callback != nullptr) { thread_branch_callback = m_branch_callback; m_branch_callback = nullptr; - m_pending_request = nullptr; + destroyPendingRequest(); thread_branch_callback->Run(readBuffer, (readBytes >= 0 ? readBytes : 0)); } @@ -389,10 +396,10 @@ void *FtdiDmxThread::Run() { if (received_reply->Response()->SourceUID() == m_pending_request->DestinationUID()) { - m_pending_request = nullptr; + destroyPendingRequest(); thread_mute_callback->Run(true); } else { - m_pending_request = nullptr; + destroyPendingRequest(); thread_mute_callback->Run(false); } } else if (m_rdm_callback != nullptr) { @@ -400,10 +407,10 @@ void *FtdiDmxThread::Run() { m_rdm_callback = nullptr; if (readBytes > 0) { - m_pending_request = nullptr; + destroyPendingRequest(); thread_rdm_callback->Run(received_reply); } else { - m_pending_request = nullptr; + destroyPendingRequest(); RunRDMCallback(thread_rdm_callback, rdm::RDM_TIMEOUT); } } @@ -432,7 +439,7 @@ void *FtdiDmxThread::Run() { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; OLA_INFO << "UnMuteAllCallback"; - m_pending_request = nullptr; + destroyPendingRequest(); thread_unmute_callback->Run(); } } diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index ff4475c0b2..8bf1d87779 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -102,6 +102,7 @@ class FtdiDmxThread const ola::rdm::UIDSet &uids); void destroyPendindingCallback(ola::rdm::RDMStatusCode state); + void destroyPendingRequest(); void CheckTimeGranularity(); From 92729c427f6e2e9f86ba7a0a24474e9727fd067a Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 7 Mar 2019 04:23:45 +0200 Subject: [PATCH 34/86] Fix for OS X building on Travis modified from PR1535 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f4a479469d..86686d5ca1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -296,6 +296,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew reinstall libtool; fi #Fix a broken homebrew python upgrade - see https://github.com/Homebrew/homebrew-core/issues/26358 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python || true; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then if [ ! -d /usr/local/sbin ]; then sudo mkdir -p /usr/local/sbin && sudo chown -R $(whoami) /usr/local/sbin; fi; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ccache bison flex liblo libmicrohttpd; fi # ossp-uuid, homebrew/python/numpy and libusb already present - if [ "$TRAVIS_OS_NAME" == "osx" -a "$LIBFTDI" != "1" ]; then brew install libftdi0; fi # install libftdi0 - if [ "$TRAVIS_OS_NAME" == "osx" -a "$LIBFTDI" == "1" ]; then brew install libftdi; fi # install the latest libftdi From 5f6187e61cf848195a5703172b272f808e4c37f6 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Thu, 7 Mar 2019 23:08:33 +0200 Subject: [PATCH 35/86] Further expanded README and hopefully shut up coverity. --- plugins/ftdidmx/README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index ed5794babf..c0c0b78e42 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -1,20 +1,29 @@ -FTDI USB Chipset DMX Plugin -=========================== +# FTDI USB Chipset DMX Plugin This plugin is compatible with Enttec OpenDmx and other FTDI chipset based USB to DMX converters where the host needs to create the DMX stream itself and not the interface (the interface has no microprocessor to do so). -RDM Support ------------ +## RDM Support FTDI based chips/outputs that have the correct line biasing setup should be able to output and receive RDM packets. -At this stage not all timings are correct. +At this stage we can't guarantee that the plugin meets all timing specs since +I don't have any faulty RDM equipment to test with (I'm testing with a single +device so it could be that collisions aren't even handled properly). -RDM was tested with: - - FT4232H (USB-COM485-PLUS4) +*It is also critical that the FTDI local echo function is disabled* + +### Proper Line Biasing +For simple DMX output (and input) all that is needed is a 130 Ohm resistor +between data+ and data-. +For RDM 2 additional resistors of 680 Ohm are needed: +1. Pull-up connects between Data+ and VCC +2. Pull-down between Data- and the common/ground. + +### RDM was tested with: +- FT4232H (USB-COM485-PLUS4) ## Config file: ola-ftdidmx.conf From 1946005c67488d4a8ac3bf556ab3961a33b90a99 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 8 Mar 2019 00:55:06 +0200 Subject: [PATCH 36/86] Another attempt to appease the README markdown coverity complaints. usleep will not be addressed for now. --- plugins/ftdidmx/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index c0c0b78e42..866c9b456b 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -9,7 +9,7 @@ and not the interface (the interface has no microprocessor to do so). FTDI based chips/outputs that have the correct line biasing setup should be able to output and receive RDM packets. -At this stage we can't guarantee that the plugin meets all timing specs since +At this stage we can't guarantee that the plugin meets all timing specs since I don't have any faulty RDM equipment to test with (I'm testing with a single device so it could be that collisions aren't even handled properly). @@ -22,8 +22,8 @@ For RDM 2 additional resistors of 680 Ohm are needed: 1. Pull-up connects between Data+ and VCC 2. Pull-down between Data- and the common/ground. -### RDM was tested with: -- FT4232H (USB-COM485-PLUS4) +### RDM was tested with + - FT4232H (USB-COM485-PLUS4) ## Config file: ola-ftdidmx.conf From a4cfe30a779fdfece3a4006ff68dffb42797d9d6 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 9 Mar 2019 20:41:51 +0000 Subject: [PATCH 37/86] Add another tested interface --- plugins/ftdidmx/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index c0c0b78e42..edace2fc33 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -24,6 +24,7 @@ For RDM 2 additional resistors of 680 Ohm are needed: ### RDM was tested with: - FT4232H (USB-COM485-PLUS4) +- USB-RS485-WE-1800-BT ## Config file: ola-ftdidmx.conf From faa98ca98c16d77250a38993e766eab65eb8d11c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 9 Mar 2019 20:57:32 +0000 Subject: [PATCH 38/86] Add that the Enttec Open DMX USB doesn't work --- plugins/ftdidmx/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index edace2fc33..cbefab8df1 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -26,6 +26,9 @@ For RDM 2 additional resistors of 680 Ohm are needed: - FT4232H (USB-COM485-PLUS4) - USB-RS485-WE-1800-BT +### RDM was tested as not working with: +- Enttec Open DMX USB (we believe this may be due to incorrect line biasing) + ## Config file: ola-ftdidmx.conf `frequency = 30` From 5b150c11f8f1cb28407fee54040d1f3a4ea047a6 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 9 Mar 2019 21:00:22 +0000 Subject: [PATCH 39/86] Minor tidy up and add details of more testing --- plugins/ftdidmx/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index cbefab8df1..fec02f95b8 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -1,6 +1,6 @@ # FTDI USB Chipset DMX Plugin -This plugin is compatible with Enttec OpenDmx and other FTDI chipset based +This plugin is compatible with Enttec Open DMX USB and other FTDI chipset based USB to DMX converters where the host needs to create the DMX stream itself and not the interface (the interface has no microprocessor to do so). @@ -10,14 +10,15 @@ FTDI based chips/outputs that have the correct line biasing setup should be able to output and receive RDM packets. At this stage we can't guarantee that the plugin meets all timing specs since -I don't have any faulty RDM equipment to test with (I'm testing with a single -device so it could be that collisions aren't even handled properly). +I don't have any faulty RDM equipment to test with. It has however been tested +with multiple responders on the line and discovery works correctly. *It is also critical that the FTDI local echo function is disabled* ### Proper Line Biasing For simple DMX output (and input) all that is needed is a 130 Ohm resistor between data+ and data-. + For RDM 2 additional resistors of 680 Ohm are needed: 1. Pull-up connects between Data+ and VCC 2. Pull-down between Data- and the common/ground. From 5564a1ed9bf9ca497bcba7e9db5db715ab858ac7 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 02:59:05 +0200 Subject: [PATCH 40/86] Initial test with nanosleep(2) Since I want to fix something else commiting before work finished. Will be refactored into function later. --- plugins/ftdidmx/FtdiDmxThread.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 0f8c8b3543..9a844aba04 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -491,9 +492,23 @@ void *FtdiDmxThread::Run() { void FtdiDmxThread::CheckTimeGranularity() { TimeStamp ts1, ts2; Clock clock; + timespec req, rem; + req.tv_sec = rem.tv_sec = 0; + rem.tv_nsec = 0; + req.tv_nsec = 1000 * 1000; + int nanosleepReturn = 0; clock.CurrentTime(&ts1); - usleep(1000); + if ((nanosleepReturn = nanosleep(&req, &rem)) < 0) { + if (nanosleepReturn == EINTR) { + while (rem.tv_nsec > 0) { + req.tv_nsec = rem.tv_nsec; + nanosleep(&req, &rem); + } + } else { + OLA_WARN << "nanosleep failed with state: " << nanosleepReturn; + } + } clock.CurrentTime(&ts2); TimeInterval interval = ts2 - ts1; From d533789d3c21443433b3fd66c53a76f2589e0e64 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 03:04:28 +0200 Subject: [PATCH 41/86] Added logic for non-branch broadcast packets that I had forgotten. --- plugins/ftdidmx/FtdiDmxThread.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 9a844aba04..28c0f5a05e 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -439,9 +439,13 @@ void *FtdiDmxThread::Run() { if (m_unmute_complete != nullptr) { thread_unmute_callback = m_unmute_complete; m_unmute_complete = nullptr; - OLA_INFO << "UnMuteAllCallback"; destroyPendingRequest(); thread_unmute_callback->Run(); + } else if (m_rdm_callback != nullptr) { + thread_rdm_callback = m_rdm_callback; + m_rdm_callback = nullptr; + destroyPendingRequest(); + ola::rdm::RunRDMCallback(thread_rdm_callback, ola::rdm::RDM_WAS_BROADCAST); } } } else { From 6309300450be5cff30970bae4164022b9caddb76 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 03:24:14 +0200 Subject: [PATCH 42/86] Fix lint issue --- plugins/ftdidmx/FtdiDmxThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 28c0f5a05e..e62427f8de 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -445,7 +445,8 @@ void *FtdiDmxThread::Run() { thread_rdm_callback = m_rdm_callback; m_rdm_callback = nullptr; destroyPendingRequest(); - ola::rdm::RunRDMCallback(thread_rdm_callback, ola::rdm::RDM_WAS_BROADCAST); + ola::rdm::RunRDMCallback(thread_rdm_callback, + ola::rdm::RDM_WAS_BROADCAST); } } } else { From 4553fe3bae0fadf14f5f7b17cf3d445ef607c464 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 17:47:48 +0200 Subject: [PATCH 43/86] Extended StringToInt per request of @peternewman --- common/utils/StringUtils.cpp | 20 ++++++++++++++------ include/ola/StringUtils.h | 10 ++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/common/utils/StringUtils.cpp b/common/utils/StringUtils.cpp index c777bd016f..57f305159e 100644 --- a/common/utils/StringUtils.cpp +++ b/common/utils/StringUtils.cpp @@ -152,13 +152,16 @@ bool StringToBoolTolerant(const string &value, bool *output) { return false; } -bool StringToInt(const string &value, unsigned int *output, bool strict) { +bool StringToInt(const string &value, + unsigned int *output, + bool strict, + uint8_t base) { if (value.empty()) { return false; } char *end_ptr; errno = 0; - long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) + long long l = strtoll(value.data(), &end_ptr, base); // NOLINT(runtime/int) if (l < 0 || (l == 0 && errno != 0)) { return false; } @@ -168,10 +171,12 @@ bool StringToInt(const string &value, unsigned int *output, bool strict) { if (strict && *end_ptr != 0) { return false; } + + *output = static_cast(l); + if (l > static_cast(UINT32_MAX)) { // NOLINT(runtime/int) return false; } - *output = static_cast(l); return true; } @@ -199,16 +204,19 @@ bool StringToInt(const string &value, uint8_t *output, bool strict) { return true; } -bool StringToInt(const string &value, int *output, bool strict) { +bool StringToInt(const string &value, int *output, bool strict, uint8_t base) { if (value.empty()) { return false; } char *end_ptr; errno = 0; - long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) + long long l = strtoll(value.data(), &end_ptr, base); // NOLINT(runtime/int) if (l == 0 && errno != 0) { return false; } + + *output = static_cast(l); + if (value == end_ptr) { return false; } @@ -218,7 +226,7 @@ bool StringToInt(const string &value, int *output, bool strict) { if (l < INT32_MIN || l > INT32_MAX) { return false; } - *output = static_cast(l); + return true; } diff --git a/include/ola/StringUtils.h b/include/ola/StringUtils.h index ff88dbdca8..bd8298ac44 100644 --- a/include/ola/StringUtils.h +++ b/include/ola/StringUtils.h @@ -262,12 +262,14 @@ bool StringToBoolTolerant(const std::string &value, bool *output); * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base sets the base of the input string, default decimal (10) * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. */ bool StringToInt(const std::string &value, unsigned int *output, - bool strict = false); + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a uint16_t. @@ -300,11 +302,15 @@ bool StringToInt(const std::string &value, * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base sets the base of the input string, default decimal (10) * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ -bool StringToInt(const std::string &value, int *output, bool strict = false); +bool StringToInt(const std::string &value, + int *output, + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a int16_t. From 591234cf17827fa4bfefdc4e21c25126baf61cfa Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 17:48:33 +0200 Subject: [PATCH 44/86] Switched from use of strtoul() to ola::StringToInt() Also note the FtdiDmxOutputPort has an ID so that can be used as RDM port# --- plugins/ftdidmx/FtdiDmxDevice.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxDevice.cpp b/plugins/ftdidmx/FtdiDmxDevice.cpp index 8a6c728fb2..e47e8ae4ba 100644 --- a/plugins/ftdidmx/FtdiDmxDevice.cpp +++ b/plugins/ftdidmx/FtdiDmxDevice.cpp @@ -54,26 +54,21 @@ FtdiDmxDevice::~FtdiDmxDevice() { } bool FtdiDmxDevice::StartHook() { - char *end; unsigned int interface_count = m_widget->GetInterfaceCount(); unsigned int successfully_added = 0; + unsigned int serial = 0; OLA_INFO << "Widget " << m_widget->Name() << " has " << interface_count << " interfaces."; for (unsigned int i = 1; i <= interface_count; i++) { + if (!StringToInt(m_widget->Serial(), &serial, false, 36)) { + OLA_WARN << "StringToInt returned false, serial used: " << serial; + } FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); if (port->SetupOutput()) { - AddPort(new FtdiDmxOutputPort( - this, - port, - i, - m_frequency, - static_cast(strtol( - m_widget->Serial().c_str(), - &end, - 36)))); + AddPort(new FtdiDmxOutputPort(this, port, i, m_frequency, serial)); successfully_added += 1; } else { OLA_WARN << "Failed to add interface: " << i; From 3f60c66f1f0e06fada28f9c34fd88b123e7c050e Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 18:22:16 +0200 Subject: [PATCH 45/86] Extended README with pinouts and schematics. --- plugins/ftdidmx/README.md | 51 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 356eb77171..0bc30e53c1 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -1,8 +1,8 @@ # FTDI USB Chipset DMX Plugin -This plugin is compatible with Enttec Open DMX USB and other FTDI chipset based -USB to DMX converters where the host needs to create the DMX stream itself -and not the interface (the interface has no microprocessor to do so). +This plugin is compatible with Enttec Open DMX USB and other FTDI chipset +based USB to DMX converters where the host needs to create the DMX stream +itself and not the interface (the interface has no microprocessor to do so). ## RDM Support @@ -16,13 +16,56 @@ with multiple responders on the line and discovery works correctly. *It is also critical that the FTDI local echo function is disabled* ### Proper Line Biasing -For simple DMX output (and input) all that is needed is a 130 Ohm resistor +For simple DMX output (and input) all that is needed is a 130 Ohm resistor between data+ and data-. For RDM 2 additional resistors of 680 Ohm are needed: 1. Pull-up connects between Data+ and VCC 2. Pull-down between Data- and the common/ground. +#### Diagram + +V + --- + | + +----------+ + | | + | [680 Ohm] + |\| | + | \----------+---------- DMX Pin 3 (Data+) + | \ | + | \ [130 Ohm] + | / | + | / | + | /o---------+---------- DMX Pin 2 (Data-) + |/| | + | [680 Ohm] + | | + +----------+---------- DMX Pin 1 (Common) + | + +-------[<=20 Ohm]---+ + | | + Common ----- + --- + - + +#### FTDI Board DB9 pinouts +Based on the FTDI spec this is the pinout to be used on their DB9 connectors +and the way to connect the lines and resistors. + +1. Data- (130 Ohm -> 3, 680 Ohm -> 5) +2. Data+ (680 Ohm -> 9) +3. 130 Ohm -> 1 +4. Not used +5. GND (680 Ohm -> 1) +6. Not used +7. Short with 8 to disable echo +8. Short with 7 to disable echo +9. +5VDC (680 Ohm -> 2) + +The FTDI spec and the DMX/RDM spec disagree where the 130 Ohm resistor should +terminate, it could be that really it should be between pins 1 and 2, both +ways have worked for me for pure output, for RDM I only tested this way. + ### RDM was tested with - FT4232H (USB-COM485-PLUS4) - USB-RS485-WE-1800-BT From 7d11c58957a687e906ffe007e05c60a8fc6d476d Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 18:27:54 +0200 Subject: [PATCH 46/86] Enable Discovery-on-patch --- plugins/ftdidmx/FtdiDmxPort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index 4496c9c59b..deb4f04454 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -50,7 +50,7 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { unsigned int id, unsigned int freq, unsigned int serial) - : BasicOutputPort(parent, id, false, true), + : BasicOutputPort(parent, id, true, true), m_interface(interface), m_thread(interface, freq, serial) { m_thread.Start(); From f7489b68894096f7a6d56143544a7d78d095c20e Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 20:27:33 +0200 Subject: [PATCH 47/86] Modify the description generator so that subsequent stuff doesn't blow up on 'escape sequences'. Also add backticks to README to signify that this is "code" --- plugins/convert_README_to_header.sh | 6 +++--- plugins/ftdidmx/README.md | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/convert_README_to_header.sh b/plugins/convert_README_to_header.sh index 86b1b42f09..62357c0a6d 100755 --- a/plugins/convert_README_to_header.sh +++ b/plugins/convert_README_to_header.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # A simple script to build a C++ header file containing the plugin description # from the plugin's README.md @@ -30,8 +30,8 @@ outfilename=`basename $outfile`; # See http://stackoverflow.com/a/16576291 # On Mac OS's sed, \n is not recognized as a newline character, but # \[actual newline] works -desc=`sed -e ':a' -e 'N' -e '$!ba' -e 's/\"/\\\"/g' -e 's/\n/\\\\n"\\ -"/g' "$path/README.md"`; +desc=`sed -e ':a' -e 'N' -e '$!ba' -e 's#\\\#\\\\\\\#g' -e 's#\"#\\\"#g' -e 's#\n#\\\\n"\\ +"#g' "$path/README.md"`; identifier=`echo "PLUGINS_${plugin}_${outfilename%.h}_H_" | tr '[:lower:]' '[:upper:]'` diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 0bc30e53c1..1302220989 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -24,6 +24,7 @@ For RDM 2 additional resistors of 680 Ohm are needed: 2. Pull-down between Data- and the common/ground. #### Diagram +` +V --- | @@ -47,6 +48,7 @@ For RDM 2 additional resistors of 680 Ohm are needed: Common ----- --- - +` #### FTDI Board DB9 pinouts Based on the FTDI spec this is the pinout to be used on their DB9 connectors From c4d0ee3b8aac06123ba5a5a5b1cd4c8d389aefe7 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 20:37:50 +0200 Subject: [PATCH 48/86] Fix comments from @peternewman --- plugins/ftdidmx/FtdiDmxThread.cpp | 6 +++--- plugins/ftdidmx/FtdiWidget.cpp | 9 ++++----- plugins/ftdidmx/README.md | 3 ++- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index e62427f8de..160252602b 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -112,9 +112,9 @@ void FtdiDmxThread::SendRDMRequest(ola::rdm::RDMRequest *request, void FtdiDmxThread::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_discovery_agent.StartFullDiscovery( - ola::NewSingleCallback(this, - &FtdiDmxThread::DiscoveryComplete, - callback)); + ola::NewSingleCallback(this, + &FtdiDmxThread::DiscoveryComplete, + callback)); } void FtdiDmxThread::RunIncrementalDiscovery(rdm::RDMDiscoveryCallback *cb) { diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 4c784fc0d9..eeba778df1 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -387,21 +387,20 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { } else if (bytesWritten == static_cast(packet->size())) { return true; } else { - OLA_WARN << "Bytes Written: " << bytesWritten << " Packet Size: " << size; + OLA_WARN << "Bytes Written: " << bytesWritten \ + << " != Packet Size: " << size; return false; } } int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); - OLA_INFO << "FtdiRead"; + OLA_DEBUG << "ftdi_read_data() read: " << read; if (read <= 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); - return read; - } else { - return read; } + return read; } bool FtdiInterface::SetupOutput() { diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 1302220989..72a1f3b4c8 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -1,4 +1,5 @@ -# FTDI USB Chipset DMX Plugin +FTDI USB Chipset DMX Plugin +=========================== This plugin is compatible with Enttec Open DMX USB and other FTDI chipset based USB to DMX converters where the host needs to create the DMX stream From c8e010fe893caa0625d2a7368c3b023e6536c392 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 20:57:57 +0200 Subject: [PATCH 49/86] Minor: remove backticks, they mess up display on github --- plugins/ftdidmx/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 72a1f3b4c8..2ae97d7ef0 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -25,7 +25,6 @@ For RDM 2 additional resistors of 680 Ohm are needed: 2. Pull-down between Data- and the common/ground. #### Diagram -` +V --- | @@ -49,7 +48,6 @@ For RDM 2 additional resistors of 680 Ohm are needed: Common ----- --- - -` #### FTDI Board DB9 pinouts Based on the FTDI spec this is the pinout to be used on their DB9 connectors From 7bf7ea5d857ab1f17a923bdb0d590783945513c9 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 21:10:02 +0200 Subject: [PATCH 50/86] Github display fix --- plugins/ftdidmx/README.md | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 2ae97d7ef0..c1dc8fbdbb 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -25,29 +25,29 @@ For RDM 2 additional resistors of 680 Ohm are needed: 2. Pull-down between Data- and the common/ground. #### Diagram - +V - --- - | - +----------+ - | | - | [680 Ohm] - |\| | - | \----------+---------- DMX Pin 3 (Data+) - | \ | - | \ [130 Ohm] - | / | - | / | - | /o---------+---------- DMX Pin 2 (Data-) - |/| | - | [680 Ohm] - | | - +----------+---------- DMX Pin 1 (Common) - | - +-------[<=20 Ohm]---+ - | | - Common ----- - --- - - + +V + --- + | + +----------+ + | | + | [680 Ohm] + |\| | + | \----------+---------- DMX Pin 3 (Data+) + | \ | + | \ [130 Ohm] + | / | + | / | + | /o---------+---------- DMX Pin 2 (Data-) + |/| | + | [680 Ohm] + | | + +----------+---------- DMX Pin 1 (Common) + | + +-------[<=20 Ohm]---+ + | | + Common ----- + --- + - #### FTDI Board DB9 pinouts Based on the FTDI spec this is the pinout to be used on their DB9 connectors From 6f84568c3ee9b485e66f6a9d74347907f1c64dc3 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 22:28:39 +0200 Subject: [PATCH 51/86] Changed to using only last 6 characters of serial. First 2 are supposed to be FT though if the product is a rebrand they may be something else. --- plugins/ftdidmx/FtdiDmxDevice.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxDevice.cpp b/plugins/ftdidmx/FtdiDmxDevice.cpp index e47e8ae4ba..720f19b998 100644 --- a/plugins/ftdidmx/FtdiDmxDevice.cpp +++ b/plugins/ftdidmx/FtdiDmxDevice.cpp @@ -62,8 +62,9 @@ bool FtdiDmxDevice::StartHook() { << " interfaces."; for (unsigned int i = 1; i <= interface_count; i++) { - if (!StringToInt(m_widget->Serial(), &serial, false, 36)) { - OLA_WARN << "StringToInt returned false, serial used: " << serial; + if (!StringToInt(m_widget->Serial().substr(2,6), &serial, false, 36)) { + OLA_WARN << "StringToInt returned false, serial used: " << serial + << " Generated from: " << m_widget->Serial().substr(2,6); } FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); From f144552085ee2de6d652e645683d422608bf737b Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 10 Mar 2019 22:29:56 +0200 Subject: [PATCH 52/86] Various comments by @peternewman fixed. --- plugins/convert_README_to_header.sh | 2 +- plugins/ftdidmx/FtdiDmxThread.cpp | 9 ++++++--- plugins/ftdidmx/FtdiWidget.cpp | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/plugins/convert_README_to_header.sh b/plugins/convert_README_to_header.sh index 62357c0a6d..e64c215822 100755 --- a/plugins/convert_README_to_header.sh +++ b/plugins/convert_README_to_header.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # A simple script to build a C++ header file containing the plugin description # from the plugin's README.md diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 160252602b..b4dcf49399 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -193,7 +193,8 @@ void FtdiDmxThread::MuteDevice(const ola::rdm::UID &target, m_mute_complete = mute_complete; m_pending_request = ola::rdm::NewMuteRequest(m_uid, target, - m_transaction_number += 1); + m_transaction_number); + m_transaction_number++; } else { // Already pending request OLA_WARN << "Unable to queue Mute request, " @@ -208,7 +209,8 @@ void FtdiDmxThread::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { m_unmute_complete = unmute_complete; m_pending_request = ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), - m_transaction_number += 1); + m_transaction_number); + m_transaction_number++; } else { // Already pending request OLA_WARN << "Unable to queue UnMuteAll request, " @@ -227,7 +229,8 @@ void FtdiDmxThread::Branch(const ola::rdm::UID &lower, ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, - m_transaction_number += 1); + m_transaction_number); + m_transaction_number++; } else { // Already pending request OLA_WARN << "Unable to queue Branch request, " diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index eeba778df1..ad4fcf0d77 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -384,19 +384,19 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; - } else if (bytesWritten == static_cast(packet->size())) { - return true; - } else { - OLA_WARN << "Bytes Written: " << bytesWritten \ + } else if (bytesWritten != static_cast(packet->size())) { + OLA_WARN << "Bytes Written: " << bytesWritten << " != Packet Size: " << size; return false; + } else { + return true; } } int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); OLA_DEBUG << "ftdi_read_data() read: " << read; - if (read <= 0) { + if (read < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); } From 6b08435be2756288a330dfa56a74846c178c468c Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 11 Mar 2019 02:22:36 +0200 Subject: [PATCH 53/86] Experimental replacement for usleep based on nanosleep. I expect it will be moved to a different part of the code if accepted. --- plugins/ftdidmx/FtdiDmxThread.cpp | 68 +++++++++++++++++++++---------- plugins/ftdidmx/FtdiDmxThread.h | 6 +++ 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index b4dcf49399..32d9c15735 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -314,7 +315,7 @@ void *FtdiDmxThread::Run() { } if (m_granularity == GOOD) { - usleep(DMX_BREAK); + expirimentalSleep(DMX_BREAK); } if (!m_interface->SetBreak(false)) { @@ -322,7 +323,7 @@ void *FtdiDmxThread::Run() { } if (m_granularity == GOOD) { - usleep(DMX_MAB); + expirimentalSleep(DMX_MAB); } if (!sendRDM) { @@ -335,7 +336,7 @@ void *FtdiDmxThread::Run() { if (m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; if (m_pending_request->IsDUB()) { - usleep(MIN_WAIT_DUB_US); + expirimentalSleep(MIN_WAIT_DUB_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); OLA_INFO << "DUB Read: " << readBytes; @@ -347,7 +348,7 @@ void *FtdiDmxThread::Run() { (readBytes >= 0 ? readBytes : 0)); } } else if (!m_pending_request->DestinationUID().IsBroadcast()) { - usleep(MIN_WAIT_RDM_US); + expirimentalSleep(MIN_WAIT_RDM_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); if (readBytes > 0) { @@ -359,7 +360,7 @@ void *FtdiDmxThread::Run() { if (readBytes < 4) { OLA_WARN << "FTDI Didn't receive at least 4B during minWait"; additionalWait = (MIN_WAIT_RDM_US / readBytes)*(4 - readBytes); - usleep(additionalWait); + expirimentalSleep(additionalWait); readBytes += m_interface->Read(readBuffer + readBytes, sizeof(readBuffer) - readBytes); } @@ -377,7 +378,7 @@ void *FtdiDmxThread::Run() { OLA_WARN << "FTDI Didn't receive full frame during minWait"; additionalWait = (MIN_WAIT_RDM_US / readBytes) * (readBuffer[3] - readBytes + 1); - usleep(additionalWait); + expirimentalSleep(additionalWait); readBytes += m_interface->Read( readBuffer + readBytes, sizeof(readBuffer) - readBytes); @@ -469,13 +470,13 @@ void *FtdiDmxThread::Run() { if (m_granularity == GOOD) { while (elapsed.InMilliSeconds() < frameTime) { - usleep(1000); + expirimentalSleep(1000); clock.CurrentTime(&ts2); elapsed = ts2 - ts1; } } else { // See if we can drop out of bad mode. - usleep(1000); + expirimentalSleep(1000); clock.CurrentTime(&ts3); interval = ts3 - ts2; if (interval.InMilliSeconds() < BAD_GRANULARITY_LIMIT) { @@ -500,30 +501,53 @@ void *FtdiDmxThread::Run() { void FtdiDmxThread::CheckTimeGranularity() { TimeStamp ts1, ts2; Clock clock; + + clock.CurrentTime(&ts1); + expirimentalSleep(1000); + clock.CurrentTime(&ts2); + + TimeInterval interval = ts2 - ts1; + m_granularity = (interval.InMilliSeconds() > BAD_GRANULARITY_LIMIT) ? + BAD : GOOD; + OLA_INFO << "Granularity for FTDI thread is " + << ((m_granularity == GOOD) ? "GOOD" : "BAD"); +} + +void FtdiDmxThread::expirimentalSleep(TimeInterval requested) { + timespec req; + req.tv_sec = requested.Seconds(); + req.tv_nsec = requested.MicroSeconds() * 1000; + + FtdiDmxThread::expirimentalSleep(req); +} + +void FtdiDmxThread::expirimentalSleep(uint32_t requested) { + timespec req; + req.tv_sec = requested / 1000000; + req.tv_nsec = (requested % 1000000) * 1000; + req.tv_sec = 0; + + FtdiDmxThread::expirimentalSleep(req); +} + +void FtdiDmxThread::expirimentalSleep(timespec requested) { timespec req, rem; - req.tv_sec = rem.tv_sec = 0; - rem.tv_nsec = 0; - req.tv_nsec = 1000 * 1000; + rem.tv_sec = rem.tv_nsec = 0; + req.tv_sec = requested.tv_sec; + req.tv_nsec = requested.tv_nsec; int nanosleepReturn = 0; - clock.CurrentTime(&ts1); if ((nanosleepReturn = nanosleep(&req, &rem)) < 0) { - if (nanosleepReturn == EINTR) { - while (rem.tv_nsec > 0) { + if (errno == EINTR) { + while (rem.tv_nsec > 0 || rem.tv_sec > 0) { req.tv_nsec = rem.tv_nsec; + req.tv_sec = rem.tv_sec; nanosleep(&req, &rem); } } else { - OLA_WARN << "nanosleep failed with state: " << nanosleepReturn; + OLA_WARN << "nanosleep failed with state: " << errno; } } - clock.CurrentTime(&ts2); - - TimeInterval interval = ts2 - ts1; - m_granularity = (interval.InMilliSeconds() > BAD_GRANULARITY_LIMIT) ? - BAD : GOOD; - OLA_INFO << "Granularity for FTDI thread is " - << ((m_granularity == GOOD) ? "GOOD" : "BAD"); } } // namespace ftdidmx } // namespace plugin diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 8bf1d87779..2a17ab0f83 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -26,6 +26,8 @@ #ifndef PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ #define PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ +#include + #include #include @@ -106,6 +108,10 @@ class FtdiDmxThread void CheckTimeGranularity(); + void expirimentalSleep(TimeInterval requested); + void expirimentalSleep(uint32_t requested); + void expirimentalSleep(timespec requested); + static const uint32_t DMX_MAB = 16; static const uint32_t DMX_BREAK = 110; static const uint32_t BAD_GRANULARITY_LIMIT = 3; From b6d41af59baf3abefb4f2c711f1d31957fd7c0a2 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 17 Mar 2019 11:07:10 +0200 Subject: [PATCH 54/86] Added ola::OlaSleep class based on the experimentalSleep stuff. --- common/utils/Clock.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++ include/ola/Clock.h | 23 +++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/common/utils/Clock.cpp b/common/utils/Clock.cpp index bc1544905a..be4cc1fbd2 100644 --- a/common/utils/Clock.cpp +++ b/common/utils/Clock.cpp @@ -39,6 +39,8 @@ #include #include +#include "ola/Logging.h" + namespace ola { using std::string; @@ -129,6 +131,11 @@ int64_t BaseTimeVal::InMilliSeconds() const { m_tv.tv_usec / ONE_THOUSAND); } +int64_t BaseTimeVal::InMicroSeconds() const { + return (m_tv.tv_sec * static_cast(USEC_IN_SECONDS) + + m_tv.tv_usec); +} + int64_t BaseTimeVal::AsInt() const { return (m_tv.tv_sec * static_cast(USEC_IN_SECONDS) + m_tv.tv_usec); } @@ -272,4 +279,64 @@ void MockClock::CurrentTime(TimeStamp *timestamp) const { *timestamp = tv; *timestamp += m_offset; } + +OlaSleep::OlaSleep(std::string caller) : + m_caller(caller) { +} + +/** + * @brief Check the granularity of usleep. + */ +void OlaSleep::CheckTimeGranularity() { + TimeStamp ts1, ts2; + Clock clock; + + clock.CurrentTime(&ts1); + OlaSleep::usleep(4); + clock.CurrentTime(&ts2); + + TimeInterval interval = ts2 - ts1; + m_granularity = (interval.InMicroSeconds() > BAD_GRANULARITY_LIMIT) ? + BAD : GOOD; + OLA_INFO << "Granularity for OlaSleep is " + << ((m_granularity == GOOD) ? "GOOD" : "BAD"); +} + +void OlaSleep::usleep(TimeInterval requested) { + timespec req; + req.tv_sec = requested.Seconds(); + req.tv_nsec = requested.MicroSeconds() * 1000; + + OlaSleep::usleep(req); +} + +void OlaSleep::usleep(uint32_t requested) { + timespec req; + req.tv_sec = requested / 1000000; + req.tv_nsec = (requested % 1000000) * 1000; + req.tv_sec = 0; + + OlaSleep::usleep(req); +} + +void OlaSleep::usleep(timespec requested) { + timespec req, rem; + rem.tv_sec = rem.tv_nsec = 0; + req.tv_sec = requested.tv_sec; + req.tv_nsec = requested.tv_nsec; + int nanosleepReturn = 0; + + if ((nanosleepReturn = nanosleep(&req, &rem)) < 0) { + if (errno == EINTR) { + while (rem.tv_nsec > 0 || rem.tv_sec > 0) { + req.tv_nsec = rem.tv_nsec; + req.tv_sec = rem.tv_sec; + nanosleep(&req, &rem); + } + } else { + OLA_WARN << "nanosleep failed with state: " << errno; + } + } +} + } // namespace ola diff --git a/include/ola/Clock.h b/include/ola/Clock.h index 657f75bbeb..e167ff106a 100644 --- a/include/ola/Clock.h +++ b/include/ola/Clock.h @@ -98,6 +98,12 @@ class BaseTimeVal { */ int64_t InMilliSeconds() const; + /** + * @brief Returns the entire BaseTimeVal as microseconds + * @return The entire BaseTimeVal in microseconds + */ + int64_t InMicroSeconds() const; + /** * @brief Returns the entire BaseTimeVal as microseconds * @return The entire BaseTimeVal in microseconds @@ -160,6 +166,7 @@ class TimeInterval { int32_t MicroSeconds() const { return m_interval.MicroSeconds(); } int64_t InMilliSeconds() const { return m_interval.InMilliSeconds(); } + int64_t InMicroSeconds() const { return m_interval.InMicroSeconds(); } int64_t AsInt() const { return m_interval.AsInt(); } std::string ToString() const { return m_interval.ToString(); } @@ -257,5 +264,21 @@ class MockClock: public Clock { private: TimeInterval m_offset; }; + +class OlaSleep { +public: + OlaSleep(std::string caller); + + void usleep(TimeInterval requested); + void usleep(uint32_t requested); + void usleep(timespec requested); +private: + std::string m_caller; + enum TimerGranularity { UNKNOWN, GOOD, BAD }; + static const uint32_t BAD_GRANULARITY_LIMIT = 10; + + TimerGranularity m_granularity; + void CheckTimeGranularity(); +}; } // namespace ola #endif // INCLUDE_OLA_CLOCK_H_ From 0a4a51ed63ed00632e0c931f185c242e6dd603fa Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 17 Mar 2019 11:10:54 +0200 Subject: [PATCH 55/86] Switched to using OlaSleep object, still need to remove native CheckGranularity. --- plugins/ftdidmx/FtdiDmxThread.cpp | 60 ++++++------------------------- plugins/ftdidmx/FtdiDmxThread.h | 7 +--- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 32d9c15735..e3f3813eaf 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -25,8 +25,6 @@ #include #include -#include -#include #include #include @@ -53,7 +51,8 @@ namespace ftdidmx { FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency, unsigned int serial) - : m_granularity(UNKNOWN), + : m_timer("FtdiDmxThread"), + m_granularity(UNKNOWN), m_interface(interface), m_term(false), m_frequency(frequency), @@ -315,7 +314,7 @@ void *FtdiDmxThread::Run() { } if (m_granularity == GOOD) { - expirimentalSleep(DMX_BREAK); + m_timer.usleep(DMX_BREAK); } if (!m_interface->SetBreak(false)) { @@ -323,7 +322,7 @@ void *FtdiDmxThread::Run() { } if (m_granularity == GOOD) { - expirimentalSleep(DMX_MAB); + m_timer.usleep(DMX_MAB); } if (!sendRDM) { @@ -336,7 +335,7 @@ void *FtdiDmxThread::Run() { if (m_interface->Write(&packetBuffer)) { OLA_INFO << "RDM packet written to line"; if (m_pending_request->IsDUB()) { - expirimentalSleep(MIN_WAIT_DUB_US); + m_timer.usleep(MIN_WAIT_DUB_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); OLA_INFO << "DUB Read: " << readBytes; @@ -348,7 +347,7 @@ void *FtdiDmxThread::Run() { (readBytes >= 0 ? readBytes : 0)); } } else if (!m_pending_request->DestinationUID().IsBroadcast()) { - expirimentalSleep(MIN_WAIT_RDM_US); + m_timer.usleep(MIN_WAIT_RDM_US); readBytes = m_interface->Read(readBuffer, sizeof(readBuffer)); if (readBytes > 0) { @@ -360,7 +359,7 @@ void *FtdiDmxThread::Run() { if (readBytes < 4) { OLA_WARN << "FTDI Didn't receive at least 4B during minWait"; additionalWait = (MIN_WAIT_RDM_US / readBytes)*(4 - readBytes); - expirimentalSleep(additionalWait); + m_timer.usleep(additionalWait); readBytes += m_interface->Read(readBuffer + readBytes, sizeof(readBuffer) - readBytes); } @@ -378,7 +377,7 @@ void *FtdiDmxThread::Run() { OLA_WARN << "FTDI Didn't receive full frame during minWait"; additionalWait = (MIN_WAIT_RDM_US / readBytes) * (readBuffer[3] - readBytes + 1); - expirimentalSleep(additionalWait); + m_timer.usleep(additionalWait); readBytes += m_interface->Read( readBuffer + readBytes, sizeof(readBuffer) - readBytes); @@ -470,13 +469,13 @@ void *FtdiDmxThread::Run() { if (m_granularity == GOOD) { while (elapsed.InMilliSeconds() < frameTime) { - expirimentalSleep(1000); + m_timer.usleep(1000); clock.CurrentTime(&ts2); elapsed = ts2 - ts1; } } else { // See if we can drop out of bad mode. - expirimentalSleep(1000); + m_timer.usleep(1000); clock.CurrentTime(&ts3); interval = ts3 - ts2; if (interval.InMilliSeconds() < BAD_GRANULARITY_LIMIT) { @@ -503,7 +502,7 @@ void FtdiDmxThread::CheckTimeGranularity() { Clock clock; clock.CurrentTime(&ts1); - expirimentalSleep(1000); + m_timer.usleep(1000); clock.CurrentTime(&ts2); TimeInterval interval = ts2 - ts1; @@ -512,43 +511,6 @@ void FtdiDmxThread::CheckTimeGranularity() { OLA_INFO << "Granularity for FTDI thread is " << ((m_granularity == GOOD) ? "GOOD" : "BAD"); } - -void FtdiDmxThread::expirimentalSleep(TimeInterval requested) { - timespec req; - req.tv_sec = requested.Seconds(); - req.tv_nsec = requested.MicroSeconds() * 1000; - - FtdiDmxThread::expirimentalSleep(req); -} - -void FtdiDmxThread::expirimentalSleep(uint32_t requested) { - timespec req; - req.tv_sec = requested / 1000000; - req.tv_nsec = (requested % 1000000) * 1000; - req.tv_sec = 0; - - FtdiDmxThread::expirimentalSleep(req); -} - -void FtdiDmxThread::expirimentalSleep(timespec requested) { - timespec req, rem; - rem.tv_sec = rem.tv_nsec = 0; - req.tv_sec = requested.tv_sec; - req.tv_nsec = requested.tv_nsec; - int nanosleepReturn = 0; - - if ((nanosleepReturn = nanosleep(&req, &rem)) < 0) { - if (errno == EINTR) { - while (rem.tv_nsec > 0 || rem.tv_sec > 0) { - req.tv_nsec = rem.tv_nsec; - req.tv_sec = rem.tv_sec; - nanosleep(&req, &rem); - } - } else { - OLA_WARN << "nanosleep failed with state: " << errno; - } - } -} } // namespace ftdidmx } // namespace plugin } // namespace ola diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 2a17ab0f83..30cad79b3b 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -26,8 +26,6 @@ #ifndef PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ #define PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ -#include - #include #include @@ -77,6 +75,7 @@ class FtdiDmxThread private: + ola::OlaSleep m_timer; enum TimerGranularity { UNKNOWN, GOOD, BAD }; TimerGranularity m_granularity; @@ -108,10 +107,6 @@ class FtdiDmxThread void CheckTimeGranularity(); - void expirimentalSleep(TimeInterval requested); - void expirimentalSleep(uint32_t requested); - void expirimentalSleep(timespec requested); - static const uint32_t DMX_MAB = 16; static const uint32_t DMX_BREAK = 110; static const uint32_t BAD_GRANULARITY_LIMIT = 3; From b084dcfb1aaa812596f0e15995552a4f4be7053c Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 17 Mar 2019 11:23:15 +0200 Subject: [PATCH 56/86] Added not about resistor strength and formatting changes to shut up coverity. --- plugins/ftdidmx/README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index c1dc8fbdbb..a6ab109d10 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -21,8 +21,12 @@ For simple DMX output (and input) all that is needed is a 130 Ohm resistor between data+ and data-. For RDM 2 additional resistors of 680 Ohm are needed: -1. Pull-up connects between Data+ and VCC -2. Pull-down between Data- and the common/ground. + 1. Pull-up connects between Data+ and VCC + 2. Pull-down between Data- and the common/ground. + +*Please note:* these values are based on the book "Control Freak" by Simon +Howell and are what I used in my test setup, however the standard actually +proscribes 133 Ohm and 562 Ohm resistors. #### Diagram +V @@ -53,26 +57,26 @@ For RDM 2 additional resistors of 680 Ohm are needed: Based on the FTDI spec this is the pinout to be used on their DB9 connectors and the way to connect the lines and resistors. -1. Data- (130 Ohm -> 3, 680 Ohm -> 5) -2. Data+ (680 Ohm -> 9) -3. 130 Ohm -> 1 -4. Not used -5. GND (680 Ohm -> 1) -6. Not used -7. Short with 8 to disable echo -8. Short with 7 to disable echo -9. +5VDC (680 Ohm -> 2) + 1. Data- (130 Ohm -> 3, 680 Ohm -> 5) + 2. Data+ (680 Ohm -> 9) + 3. 130 Ohm -> 1 + 4. Not used + 5. GND (680 Ohm -> 1) + 6. Not used + 7. Short with 8 to disable echo + 8. Short with 7 to disable echo + 9. +5VDC (680 Ohm -> 2) The FTDI spec and the DMX/RDM spec disagree where the 130 Ohm resistor should terminate, it could be that really it should be between pins 1 and 2, both ways have worked for me for pure output, for RDM I only tested this way. ### RDM was tested with -- FT4232H (USB-COM485-PLUS4) -- USB-RS485-WE-1800-BT + - FT4232H (USB-COM485-PLUS4) + - USB-RS485-WE-1800-BT ### RDM was tested as not working with -- Enttec Open DMX USB (we believe this may be due to incorrect line biasing) + - Enttec Open DMX USB (we believe this may be due to incorrect line biasing) ## Config file: ola-ftdidmx.conf From b489f9685b1c4582ef9d98d15c5b4a6c41a949f9 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 18:33:50 +0200 Subject: [PATCH 57/86] README layout change to satisfy the coverity demon. --- plugins/ftdidmx/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index a6ab109d10..2d567e6529 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -21,8 +21,8 @@ For simple DMX output (and input) all that is needed is a 130 Ohm resistor between data+ and data-. For RDM 2 additional resistors of 680 Ohm are needed: - 1. Pull-up connects between Data+ and VCC - 2. Pull-down between Data- and the common/ground. +1. Pull-up connects between Data+ and VCC +2. Pull-down between Data- and the common/ground. *Please note:* these values are based on the book "Control Freak" by Simon Howell and are what I used in my test setup, however the standard actually @@ -57,26 +57,26 @@ proscribes 133 Ohm and 562 Ohm resistors. Based on the FTDI spec this is the pinout to be used on their DB9 connectors and the way to connect the lines and resistors. - 1. Data- (130 Ohm -> 3, 680 Ohm -> 5) - 2. Data+ (680 Ohm -> 9) - 3. 130 Ohm -> 1 - 4. Not used - 5. GND (680 Ohm -> 1) - 6. Not used - 7. Short with 8 to disable echo - 8. Short with 7 to disable echo - 9. +5VDC (680 Ohm -> 2) +1. Data- (130 Ohm -> 3, 680 Ohm -> 5) +2. Data+ (680 Ohm -> 9) +3. 130 Ohm -> 1 +4. Not used +5. GND (680 Ohm -> 1) +6. Not used +7. Short with 8 to disable echo +8. Short with 7 to disable echo +9. +5VDC (680 Ohm -> 2) The FTDI spec and the DMX/RDM spec disagree where the 130 Ohm resistor should terminate, it could be that really it should be between pins 1 and 2, both ways have worked for me for pure output, for RDM I only tested this way. ### RDM was tested with - - FT4232H (USB-COM485-PLUS4) - - USB-RS485-WE-1800-BT +- FT4232H (USB-COM485-PLUS4) +- USB-RS485-WE-1800-BT ### RDM was tested as not working with - - Enttec Open DMX USB (we believe this may be due to incorrect line biasing) +- Enttec Open DMX USB (we believe this may be due to incorrect line biasing) ## Config file: ola-ftdidmx.conf From 8d9691d2d893a6ba8f47b9d87f8f2f9195c8d2f6 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 18:37:47 +0200 Subject: [PATCH 58/86] Rename OlaSleep to Sleep, modify & optimize some of the code. Not yet totally done. --- common/utils/Clock.cpp | 77 ++++++++++++++++++++++++++++-------------- include/ola/Clock.h | 27 ++++++++++----- 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/common/utils/Clock.cpp b/common/utils/Clock.cpp index be4cc1fbd2..ed4654f5e5 100644 --- a/common/utils/Clock.cpp +++ b/common/utils/Clock.cpp @@ -280,58 +280,83 @@ void MockClock::CurrentTime(TimeStamp *timestamp) const { *timestamp += m_offset; } -OlaSleep::OlaSleep(std::string caller) : +Sleep::Sleep(std::string caller) : m_caller(caller) { } /** - * @brief Check the granularity of usleep. + * @brief Set wanted granularity for usleep and check it. + * @note does not check at the nanosecond level, + * since internal sturtures use usecs. + * + * @param wanted wanted/needed granularity in usecs + * @param maxDeviation max deviation in usecs tolerated by calling thread. + * + * @attention the granularity of sleep is highly fluctuating depending on the + * load of the system, a prior GOOD state is no guarantee for future proper + * timing. */ -void OlaSleep::CheckTimeGranularity() { +bool Sleep::CheckTimeGranularity(uint64_t wanted, uint64_t maxDeviation) { TimeStamp ts1, ts2; Clock clock; + m_wanted_granularity = wanted; + m_max_granularity_deviation = maxDeviation; + + timespec t; + t.tv_sec = wanted / USEC_IN_SECONDS; + t.tv_nsec = (wanted % USEC_IN_SECONDS) * ONE_THOUSAND; + clock.CurrentTime(&ts1); - OlaSleep::usleep(4); + Sleep::usleep(1); clock.CurrentTime(&ts2); - TimeInterval interval = ts2 - ts1; - m_granularity = (interval.InMicroSeconds() > BAD_GRANULARITY_LIMIT) ? - BAD : GOOD; - OLA_INFO << "Granularity for OlaSleep is " - << ((m_granularity == GOOD) ? "GOOD" : "BAD"); + m_clock_overhead = interval.InMicroSeconds(); + + clock.CurrentTime(&ts1); + Sleep::usleep(t); + clock.CurrentTime(&ts2); + + interval = ts2 - ts1; + m_granularity = (interval.InMicroSeconds() > + (wanted + maxDeviation + m_clock_overhead)) ? BAD : GOOD; + + OLA_INFO << "Granularity for OlaSleep in " << m_caller << " is " + << ((m_granularity == GOOD) ? "GOOD" : "BAD") + << " Requested: " << wanted << " Got: " << interval.InMicroSeconds() + << " Overhead: " << m_clock_overhead; + if (m_granularity == GOOD) { + return true; + } + return false; } -void OlaSleep::usleep(TimeInterval requested) { +void Sleep::usleep(TimeInterval requested) { timespec req; req.tv_sec = requested.Seconds(); - req.tv_nsec = requested.MicroSeconds() * 1000; + req.tv_nsec = requested.MicroSeconds() * ONE_THOUSAND; - OlaSleep::usleep(req); + Sleep::usleep(req); } -void OlaSleep::usleep(uint32_t requested) { +void Sleep::usleep(uint32_t requested) { timespec req; - req.tv_sec = requested / 1000000; - req.tv_nsec = (requested % 1000000) * 1000; + req.tv_sec = requested / USEC_IN_SECONDS; + req.tv_nsec = (requested % USEC_IN_SECONDS) * ONE_THOUSAND; req.tv_sec = 0; - OlaSleep::usleep(req); + Sleep::usleep(req); } -void OlaSleep::usleep(timespec requested) { - timespec req, rem; - rem.tv_sec = rem.tv_nsec = 0; - req.tv_sec = requested.tv_sec; - req.tv_nsec = requested.tv_nsec; - int nanosleepReturn = 0; +void Sleep::usleep(timespec requested) { + timespec rem; - if ((nanosleepReturn = nanosleep(&req, &rem)) < 0) { + if (nanosleep(&requested, &rem) < 0) { if (errno == EINTR) { while (rem.tv_nsec > 0 || rem.tv_sec > 0) { - req.tv_nsec = rem.tv_nsec; - req.tv_sec = rem.tv_sec; - nanosleep(&req, &rem); + requested.tv_nsec = rem.tv_nsec; + requested.tv_sec = rem.tv_sec; + nanosleep(&requested, &rem); } } else { OLA_WARN << "nanosleep failed with state: " << errno; diff --git a/include/ola/Clock.h b/include/ola/Clock.h index e167ff106a..4163a9caa8 100644 --- a/include/ola/Clock.h +++ b/include/ola/Clock.h @@ -41,7 +41,9 @@ namespace ola { static const int USEC_IN_SECONDS = 1000000; -static const int ONE_THOUSAND = 1000; +static const int MSEC_IN_SEC = 1000; +static const uint64_t NSEC_IN_SEC = 1000000000; +static const int ONE_THOUSAND = MSEC_IN_SEC; /** * Don't use this class directly. It's an implementation detail of TimeInterval @@ -265,20 +267,29 @@ class MockClock: public Clock { TimeInterval m_offset; }; -class OlaSleep { -public: - OlaSleep(std::string caller); +enum TimerGranularity { UNKNOWN, GOOD, BAD }; + +class Sleep { + public: + explicit Sleep(std::string caller); + + void setCaller(std::string caller) { m_caller = caller; } void usleep(TimeInterval requested); void usleep(uint32_t requested); void usleep(timespec requested); -private: + + TimerGranularity getGranularity() { return m_granularity; } + bool CheckTimeGranularity(uint64_t wanted, uint64_t maxDeviation); + private: std::string m_caller; - enum TimerGranularity { UNKNOWN, GOOD, BAD }; + uint64_t m_wanted_granularity; + uint64_t m_max_granularity_deviation; + uint64_t m_clock_overhead; + static const uint32_t BAD_GRANULARITY_LIMIT = 10; - TimerGranularity m_granularity; - void CheckTimeGranularity(); + TimerGranularity m_granularity = UNKNOWN; }; } // namespace ola #endif // INCLUDE_OLA_CLOCK_H_ From 1e004ac505342ea684298b12c755be3c82123ada Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 20:51:48 +0200 Subject: [PATCH 59/86] Switch from Sleep::usleep() to this->usleep() --- common/utils/Clock.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/utils/Clock.cpp b/common/utils/Clock.cpp index ed4654f5e5..6e31696af0 100644 --- a/common/utils/Clock.cpp +++ b/common/utils/Clock.cpp @@ -308,13 +308,13 @@ bool Sleep::CheckTimeGranularity(uint64_t wanted, uint64_t maxDeviation) { t.tv_nsec = (wanted % USEC_IN_SECONDS) * ONE_THOUSAND; clock.CurrentTime(&ts1); - Sleep::usleep(1); + this->usleep(1); clock.CurrentTime(&ts2); TimeInterval interval = ts2 - ts1; m_clock_overhead = interval.InMicroSeconds(); clock.CurrentTime(&ts1); - Sleep::usleep(t); + this->usleep(t); clock.CurrentTime(&ts2); interval = ts2 - ts1; @@ -336,7 +336,7 @@ void Sleep::usleep(TimeInterval requested) { req.tv_sec = requested.Seconds(); req.tv_nsec = requested.MicroSeconds() * ONE_THOUSAND; - Sleep::usleep(req); + this->usleep(req); } void Sleep::usleep(uint32_t requested) { @@ -345,7 +345,7 @@ void Sleep::usleep(uint32_t requested) { req.tv_nsec = (requested % USEC_IN_SECONDS) * ONE_THOUSAND; req.tv_sec = 0; - Sleep::usleep(req); + this->usleep(req); } void Sleep::usleep(timespec requested) { From c22294319129399db230e95aec6806ed23e3714c Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 20:52:39 +0200 Subject: [PATCH 60/86] Added which output port the Interface deals with in Description() --- plugins/ftdidmx/FtdiWidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 25e2e2d314..aee5579e4f 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -154,7 +154,7 @@ class FtdiWidget { uint32_t Id() const { return m_id; } std::string Description() const { - return m_name + " with serial number : " + m_serial +" "; + return m_name + " serial: " + m_serial + " port: " + std::to_string(m_id); } /** @brief Get Widget available interface count **/ From 8410da0aac5e17b5ffbe7d35c0c446249ce51427 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 22:34:45 +0200 Subject: [PATCH 61/86] Make sure the Widget 'knows' the correct interface. --- plugins/ftdidmx/FtdiWidget.cpp | 3 ++- plugins/ftdidmx/FtdiWidget.h | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index ad4fcf0d77..0f5d1f6cef 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -217,7 +217,7 @@ void FtdiWidget::Widgets(vector *widgets) { ftdi_free(ftdi); } -FtdiInterface::FtdiInterface(const FtdiWidget * parent, +FtdiInterface::FtdiInterface(FtdiWidget *parent, const ftdi_interface interface) : m_parent(parent), m_interface(interface) { @@ -235,6 +235,7 @@ FtdiInterface::~FtdiInterface() { bool FtdiInterface::SetInterface() { OLA_INFO << "Setting interface to: " << m_interface; + m_parent->setId(static_cast(m_interface)); if (ftdi_set_interface(&m_handle, m_interface) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index aee5579e4f..2817cbc340 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -153,6 +153,8 @@ class FtdiWidget { /** @brief Get the widget's FTD2XX ID number */ uint32_t Id() const { return m_id; } + void setId(uint32_t id) { m_id = id; } + std::string Description() const { return m_name + " serial: " + m_serial + " port: " + std::to_string(m_id); } @@ -182,7 +184,7 @@ class FtdiWidget { class FtdiInterface { public: - FtdiInterface(const FtdiWidget * parent, + FtdiInterface(FtdiWidget * parent, const ftdi_interface interface); virtual ~FtdiInterface(); @@ -238,7 +240,7 @@ class FtdiInterface { bool SetupOutput(); private: - const FtdiWidget * m_parent; + FtdiWidget * m_parent; struct ftdi_context m_handle; const ftdi_interface m_interface; }; // FtdiInterface From 6252026ebf390b1ed8450e9a3f2beb27c1931a06 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 22:35:41 +0200 Subject: [PATCH 62/86] Lint fix --- plugins/ftdidmx/FtdiDmxDevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxDevice.cpp b/plugins/ftdidmx/FtdiDmxDevice.cpp index 720f19b998..ccb17822d1 100644 --- a/plugins/ftdidmx/FtdiDmxDevice.cpp +++ b/plugins/ftdidmx/FtdiDmxDevice.cpp @@ -62,9 +62,9 @@ bool FtdiDmxDevice::StartHook() { << " interfaces."; for (unsigned int i = 1; i <= interface_count; i++) { - if (!StringToInt(m_widget->Serial().substr(2,6), &serial, false, 36)) { + if (!StringToInt(m_widget->Serial().substr(2, 6), &serial, false, 36)) { OLA_WARN << "StringToInt returned false, serial used: " << serial - << " Generated from: " << m_widget->Serial().substr(2,6); + << " Generated from: " << m_widget->Serial().substr(2, 6); } FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); From 3c5a2e682aa1eae78f2e21348a63c2e6bf052ca5 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 19 Mar 2019 22:36:37 +0200 Subject: [PATCH 63/86] Detailed caller string for Sleep, some changes with granularity check, more changes to come. --- plugins/ftdidmx/FtdiDmxThread.cpp | 16 ++++------------ plugins/ftdidmx/FtdiDmxThread.h | 3 +-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index e3f3813eaf..e6ff15ae32 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -64,6 +64,7 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, m_mute_complete(nullptr), m_unmute_complete(nullptr), m_branch_callback(nullptr) { + m_timer.setCaller("FtdiDmxThread " + m_interface->Description()); } FtdiDmxThread::~FtdiDmxThread() { @@ -475,6 +476,7 @@ void *FtdiDmxThread::Run() { } } else { // See if we can drop out of bad mode. + CheckTimeGranularity(); m_timer.usleep(1000); clock.CurrentTime(&ts3); interval = ts3 - ts2; @@ -498,18 +500,8 @@ void *FtdiDmxThread::Run() { * @brief Check the granularity of usleep. */ void FtdiDmxThread::CheckTimeGranularity() { - TimeStamp ts1, ts2; - Clock clock; - - clock.CurrentTime(&ts1); - m_timer.usleep(1000); - clock.CurrentTime(&ts2); - - TimeInterval interval = ts2 - ts1; - m_granularity = (interval.InMilliSeconds() > BAD_GRANULARITY_LIMIT) ? - BAD : GOOD; - OLA_INFO << "Granularity for FTDI thread is " - << ((m_granularity == GOOD) ? "GOOD" : "BAD"); + m_timer.CheckTimeGranularity(8, 4); + m_granularity = m_timer.getGranularity(); } } // namespace ftdidmx } // namespace plugin diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 30cad79b3b..7113cccddd 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -75,8 +75,7 @@ class FtdiDmxThread private: - ola::OlaSleep m_timer; - enum TimerGranularity { UNKNOWN, GOOD, BAD }; + ola::Sleep m_timer; TimerGranularity m_granularity; FtdiInterface *m_interface; From 4e285cb6013cee5408bf6310964026b9a00a991b Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 20 Mar 2019 22:04:20 +0200 Subject: [PATCH 64/86] Set a random deviceId for a device lacking a serial number in the thread. It is probably better to use a FTDI flashing program and write your own serial into the chip then leave the situation like this. --- plugins/ftdidmx/FtdiDmxThread.cpp | 7 +++++++ plugins/ftdidmx/FtdiDmxThread.h | 2 +- plugins/ftdidmx/FtdiWidget.cpp | 4 ---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index e6ff15ae32..fdf10d64f0 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -65,6 +65,13 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, m_unmute_complete(nullptr), m_branch_callback(nullptr) { m_timer.setCaller("FtdiDmxThread " + m_interface->Description()); + + if (serial == 0) { + unsigned int deviceId = std::rand(); + OLA_WARN << "Setting Device ID to random value due to lack of serial: " + << deviceId; + m_uid = ola::rdm::UID(OPEN_LIGHTING_ESTA_CODE, deviceId); + } } FtdiDmxThread::~FtdiDmxThread() { diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 7113cccddd..45abc445c3 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -89,7 +89,7 @@ class FtdiDmxThread uint8_t m_transaction_number; ola::rdm::DiscoveryAgent m_discovery_agent; - const ola::rdm::UID m_uid; + ola::rdm::UID m_uid; ola::rdm::RDMRequest *m_pending_request; ola::rdm::RDMCallback *m_rdm_callback; diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 0f5d1f6cef..10e221fca7 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -190,10 +190,6 @@ void FtdiWidget::Widgets(vector *widgets) { } } - /* TODO: Serial part of UID for RDM relies on serial, - * need to add a default serial - */ - OLA_INFO << "Found FTDI device. Vendor: '" << v << "', Name: '" << sname << "', Serial: '" << sserial << "'"; ToUpper(&v); From c912c7fd6a7cad84a528756d1a9ab4303f619f29 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 20 Mar 2019 22:53:22 +0200 Subject: [PATCH 65/86] Some doxygen changes --- plugins/ftdidmx/FtdiDmxThread.cpp | 6 +++--- plugins/ftdidmx/FtdiDmxThread.h | 12 +++++++++++- plugins/ftdidmx/FtdiWidget.h | 12 +++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index fdf10d64f0..fd76a1b2ae 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -154,10 +154,10 @@ void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, /** * @brief Method called to cleanup any outstanding callbacks - * @param state + * @param state state to return to caller when possible. * - * All callbacks except the RDMCallback lack a way of reporting an error state - * to the caller. + * @note All callbacks except the RDMCallback lack a way of reporting an error + * state to the caller. */ void FtdiDmxThread::destroyPendindingCallback(ola::rdm::RDMStatusCode state) { MuteDeviceCallback *thread_mute_callback = nullptr; diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 45abc445c3..34a2064d09 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -100,8 +100,18 @@ class FtdiDmxThread void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool status, const ola::rdm::UIDSet &uids); - + /** + * @brief Method called to cleanup any outstanding callbacks + * @param state state to return to caller when possible. + * + * @note All callbacks except the RDMCallback lack a way of reporting an + * error state to the caller. + */ void destroyPendindingCallback(ola::rdm::RDMStatusCode state); + /** + * @brief Method called to cleanup the pending request without leaking + * memory. + */ void destroyPendingRequest(); void CheckTimeGranularity(); diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 2817cbc340..5515364b5e 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -193,7 +193,7 @@ class FtdiInterface { return m_parent->Description(); } - /** @brief Set interface on the widget */ + /** @brief Pick interface on multiport widgets */ bool SetInterface(); /** @brief Open the widget */ @@ -230,10 +230,16 @@ class FtdiInterface { bool Write(const ola::DmxBuffer &data); /** @brief Write prepared packets to previously opened line, - * agnostic to packet contents */ + * agnostic to packet contents + * @pre The whole line setup and opening sequence. + * Should haven been performed by the plugin before ever reaching this. + */ bool Write(ola::io::ByteString *packet); - /** @brief Read data from a previously-opened line */ + /** @brief Read data from a previously-opened line + * @pre The whole line setup and opening sequence. + * Should haven been performed by the plugin before ever reaching this. + */ int Read(unsigned char* buff, int size); /** @brief Setup device for DMX Output **/ From a90c1ba8162bb062de4184b13d18f63cc16a65cb Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Wed, 20 Mar 2019 22:54:24 +0200 Subject: [PATCH 66/86] Forgot to seed pseudo random number generator. --- plugins/ftdidmx/FtdiDmxThread.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index fd76a1b2ae..2827d2b2df 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -67,6 +67,7 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, m_timer.setCaller("FtdiDmxThread " + m_interface->Description()); if (serial == 0) { + std::srand(std::time(nullptr)); unsigned int deviceId = std::rand(); OLA_WARN << "Setting Device ID to random value due to lack of serial: " << deviceId; From 8b9ff70c22378c423fe2728e4c468bdc5c3973c0 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Sun, 28 Jul 2019 18:16:47 +0300 Subject: [PATCH 67/86] Added echo detection function, initially added at thread level however seems more logical at hw level so moved there. Thread level function still commented out in code will be removed later. The thread does not seem to need to be echo aware, however once I do tests we'll know for sure. --- plugins/ftdidmx/FtdiDmxThread.cpp | 45 ++++++++++++++++++++++++++++++- plugins/ftdidmx/FtdiWidget.cpp | 38 +++++++++++++++++++++++++- plugins/ftdidmx/FtdiWidget.h | 9 +++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 2827d2b2df..fbbd47984c 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -52,7 +52,7 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency, unsigned int serial) : m_timer("FtdiDmxThread"), - m_granularity(UNKNOWN), + m_granularity(TimerGranularity::UNKNOWN), m_interface(interface), m_term(false), m_frequency(frequency), @@ -511,6 +511,49 @@ void FtdiDmxThread::CheckTimeGranularity() { m_timer.CheckTimeGranularity(8, 4); m_granularity = m_timer.getGranularity(); } + +/** + * @brief FtdiDmxThread::CheckEchoState + * @return true is echo is on + * + * echo is always assumed on unless proven otherwise. + * +bool FtdiDmxThread::CheckEchoState() { + ola::io::ByteString testPattern; + testPattern.push_back(0xff); + testPattern.push_back(0x55); + testPattern.push_back(0xff); + testPattern.push_back(0xaa); + testPattern.push_back(0xff); + testPattern.push_back(0x55); + testPattern.push_back(0xff); + testPattern.push_back(0xaa); + testPattern.push_back(0xff); + testPattern.push_back(0x55); + testPattern.push_back(0xff); + testPattern.push_back(0xaa); + + unsigned char readBuffer[13]; + int readBytes; + + if(!m_interface->PurgeBuffers()) { + OLA_WARN << "Failed to clear buffers so can't verify echo state."; + return true; + } + + if(m_interface->Write(&testPattern)) { + readBytes = m_interface->Read(readBuffer, 13); + if(readBytes == 0) { + return false; + } else { + // check other + } + } else { + //handle write error + } + // If we can't verify beyond a doubt that echo is off it is assumed on. + return true; +}*/ } // namespace ftdidmx } // namespace plugin } // namespace ola diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 10e221fca7..9dea88b4c3 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -216,7 +216,8 @@ void FtdiWidget::Widgets(vector *widgets) { FtdiInterface::FtdiInterface(FtdiWidget *parent, const ftdi_interface interface) : m_parent(parent), - m_interface(interface) { + m_interface(interface), + m_echoState(UNKNOWN) { memset(&m_handle, '\0', sizeof(struct ftdi_context)); ftdi_init(&m_handle); } @@ -400,6 +401,41 @@ int FtdiInterface::Read(unsigned char *buff, int size) { return read; } +void FtdiInterface::DetectEchoState() { + unsigned char testPattern[] = "\xff\x55\xff\xaa\xff\x0f\xf0"; + int size = sizeof(testPattern); + unsigned char readBuffer[(size + 1)]; + + int bytesWritten = ftdi_write_data(&m_handle, testPattern, size); + if (bytesWritten < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + m_echoState = UNKNOWN; + return; + } else if (bytesWritten != size) { + OLA_WARN << "Bytes Written: " << bytesWritten + << " != Pattern Size: " << size + << " Attempting detection of what was written."; + } + int bytesRead = ftdi_read_data(&m_handle, readBuffer, bytesWritten); + if(bytesRead == 0) { + m_echoState = OFF; + } else if(bytesRead < 0) { + OLA_WARN << m_parent->Description() << " " + << ftdi_get_error_string(&m_handle); + m_echoState = UNKNOWN; + return; + } else if(bytesRead <= bytesWritten) { + for (int i = 0; i < bytesRead; i++) { + if(testPattern[i] != readBuffer[i]) { + m_echoState = UNKNOWN; + return; + } + } + } + m_echoState = ON; +} + bool FtdiInterface::SetupOutput() { // Setup the widget if (!SetInterface()) { diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 5515364b5e..2abab83d4f 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -182,6 +182,12 @@ class FtdiWidget { const uint16_t m_pid; }; +enum EchoState { + UNKNOWN, + ON, + OFF +}; + class FtdiInterface { public: FtdiInterface(FtdiWidget * parent, @@ -242,6 +248,8 @@ class FtdiInterface { */ int Read(unsigned char* buff, int size); + void DetectEchoState(); + /** @brief Setup device for DMX Output **/ bool SetupOutput(); @@ -249,6 +257,7 @@ class FtdiInterface { FtdiWidget * m_parent; struct ftdi_context m_handle; const ftdi_interface m_interface; + EchoState m_echoState; }; // FtdiInterface } // namespace ftdidmx } // namespace plugin From c2083af21a870f8c073b74d83020bfb4a4607eee Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 17:39:34 +0300 Subject: [PATCH 68/86] Switch from srand to ola::math::Random() --- plugins/ftdidmx/FtdiDmxThread.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index fbbd47984c..116dbe5991 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -41,6 +42,8 @@ #include "ola/rdm/RDMResponseCodes.h" #include "ola/rdm/DiscoveryAgent.h" +#include "ola/math/Random.h" + #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" @@ -67,8 +70,8 @@ FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, m_timer.setCaller("FtdiDmxThread " + m_interface->Description()); if (serial == 0) { - std::srand(std::time(nullptr)); - unsigned int deviceId = std::rand(); + ola::math::InitRandom(); + unsigned int deviceId = ola::math::Random(0, INT_MAX); OLA_WARN << "Setting Device ID to random value due to lack of serial: " << deviceId; m_uid = ola::rdm::UID(OPEN_LIGHTING_ESTA_CODE, deviceId); From 717462d262ffe3bb4cfa0ff8053aa473d7376287 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 17:40:24 +0300 Subject: [PATCH 69/86] Add LOG/DEBUG outputs to echo detection --- plugins/ftdidmx/FtdiWidget.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 9dea88b4c3..92a9fa14dc 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -419,20 +419,26 @@ void FtdiInterface::DetectEchoState() { } int bytesRead = ftdi_read_data(&m_handle, readBuffer, bytesWritten); if(bytesRead == 0) { + OLA_LOG << m_parent->Description() << " No data read, echo state OFF."; m_echoState = OFF; } else if(bytesRead < 0) { OLA_WARN << m_parent->Description() << " " - << ftdi_get_error_string(&m_handle); + << ftdi_get_error_string(&m_handle) << "\n" + << "Echo state UNKNOWN"; m_echoState = UNKNOWN; return; } else if(bytesRead <= bytesWritten) { for (int i = 0; i < bytesRead; i++) { if(testPattern[i] != readBuffer[i]) { m_echoState = UNKNOWN; + OLA_WARN << m_parent->Description() + << "Mismatch in read data and test pattern, " + << "echo state remains UNKNOWN."; return; } } } + OLA_LOG << m_parent->Description() << "Echo state ON."; m_echoState = ON; } From 7b0ecf868967e27b26a8a44794cbaca15b772d72 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 18:29:37 +0300 Subject: [PATCH 70/86] Add logic to Write(ola::io::ByteString) to skip written bytes if echo is ON. Also fixed debug output targets to right targets. TODO: Add echo detection to setup. TODO: Convert Write(DmxBuffer) to use Write(ola::io::ByteString) --- plugins/ftdidmx/FtdiWidget.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 92a9fa14dc..caf90df996 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -378,6 +378,15 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { packet->size()); int size = packet->size(); + + /* In case echo may be on immediately read the amount of bytes that were + * put on the line so that read will start at point of reception. + */ + if (bytesWritten > 0 && m_echoState != OFF) { + unsigned char readBuffer[bytesWritten]; + ftdi_read_data(&m_handle, readBuffer, bytesWritten); + } + if (bytesWritten < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); @@ -419,7 +428,7 @@ void FtdiInterface::DetectEchoState() { } int bytesRead = ftdi_read_data(&m_handle, readBuffer, bytesWritten); if(bytesRead == 0) { - OLA_LOG << m_parent->Description() << " No data read, echo state OFF."; + OLA_INFO << m_parent->Description() << " No data read, echo state OFF."; m_echoState = OFF; } else if(bytesRead < 0) { OLA_WARN << m_parent->Description() << " " @@ -438,7 +447,7 @@ void FtdiInterface::DetectEchoState() { } } } - OLA_LOG << m_parent->Description() << "Echo state ON."; + OLA_INFO << m_parent->Description() << "Echo state ON."; m_echoState = ON; } From ed1eb6b48e781eaa771a194260e57cd7955c5710 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 21:52:51 +0300 Subject: [PATCH 71/86] Disable auto discovery. As mentioned on IRC it seems to me that this behavior is not desirable. --- plugins/ftdidmx/FtdiDmxPort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxPort.h b/plugins/ftdidmx/FtdiDmxPort.h index deb4f04454..4496c9c59b 100644 --- a/plugins/ftdidmx/FtdiDmxPort.h +++ b/plugins/ftdidmx/FtdiDmxPort.h @@ -50,7 +50,7 @@ class FtdiDmxOutputPort : public ola::BasicOutputPort { unsigned int id, unsigned int freq, unsigned int serial) - : BasicOutputPort(parent, id, true, true), + : BasicOutputPort(parent, id, false, true), m_interface(interface), m_thread(interface, freq, serial) { m_thread.Start(); From 5392ab06370b8e4e669675e1a63d87b858db9a2a Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 21:54:30 +0300 Subject: [PATCH 72/86] Allow RDM to continue if no pending DMX packet and less then second passed. --- plugins/ftdidmx/FtdiDmxThread.cpp | 4 +++- plugins/ftdidmx/FtdiDmxThread.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index 116dbe5991..dcdce8cf9f 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -298,7 +298,9 @@ void *FtdiDmxThread::Run() { if (m_pending_request != nullptr) { elapsed = ts1 - lastDMX; - if (elapsed.InMilliSeconds() < HALF_SECOND_MS) { + if (elapsed.InMilliSeconds() < HALF_SECOND_MS || + (buffer.Size() < 24 && + elapsed.InMilliSeconds() < ALMOST_SECOND_MS)) { if (!packetBuffer.empty()) { packetBuffer.clear(); } diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 34a2064d09..22eb2c53e7 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -41,6 +41,7 @@ namespace ftdidmx { enum { HALF_SECOND_MS = 500, + ALMOST_SECOND_MS = 900, MIN_WAIT_DUB_US = 58000, MIN_WAIT_RDM_US = 30000, }; From c666d7197c256700d127f50dce47a20fdd6a7307 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 21:58:16 +0300 Subject: [PATCH 73/86] Attempt at making Write(DmxBuffer) use Write(ola::io::ByteString) so far causes crashes because Size() is too often 0 instead of within allowed range. --- plugins/ftdidmx/FtdiWidget.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index caf90df996..5ddb0699f9 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -355,7 +355,18 @@ bool FtdiInterface::SetBreak(bool on) { } bool FtdiInterface::Write(const ola::DmxBuffer& data) { - unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; + ola::io::ByteString packetBuffer; + packetBuffer[0] = DMX512_START_CODE; + + if(data.Size() >= 24) { + packetBuffer.insert(1, data.GetRaw(), data.Size()); + } else { + OLA_WARN << m_parent->Description() << " Broadcasting NULL DMX Package due to empty buffer."; + packetBuffer.append(512, '\x00'); + } + + return Write(&packetBuffer); +/* unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; unsigned int length = DMX_UNIVERSE_SIZE; buffer[0] = DMX512_START_CODE; @@ -367,7 +378,7 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { return false; } else { return true; - } + }*/ } @@ -384,7 +395,9 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { */ if (bytesWritten > 0 && m_echoState != OFF) { unsigned char readBuffer[bytesWritten]; - ftdi_read_data(&m_handle, readBuffer, bytesWritten); + int read = ftdi_read_data(&m_handle, readBuffer, bytesWritten); + OLA_DEBUG << m_parent->Description() + << "Write() - Wrote: " << bytesWritten << " Read: " << read; } if (bytesWritten < 0) { @@ -441,13 +454,13 @@ void FtdiInterface::DetectEchoState() { if(testPattern[i] != readBuffer[i]) { m_echoState = UNKNOWN; OLA_WARN << m_parent->Description() - << "Mismatch in read data and test pattern, " + << " Mismatch in read data and test pattern, " << "echo state remains UNKNOWN."; return; } } } - OLA_INFO << m_parent->Description() << "Echo state ON."; + OLA_INFO << m_parent->Description() << " Echo state ON."; m_echoState = ON; } @@ -493,6 +506,8 @@ bool FtdiInterface::SetupOutput() { return false; } + DetectEchoState(); + return true; } From 249d82606c5466c2aa0c456da541d88ffbe01b7a Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Mon, 29 Jul 2019 22:59:28 +0300 Subject: [PATCH 74/86] Fix description string to actually reflect what port is being used. --- plugins/ftdidmx/FtdiWidget.cpp | 59 ++++++++++++++++++++++------------ plugins/ftdidmx/FtdiWidget.h | 6 ++-- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 5ddb0699f9..09487cf297 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -230,11 +230,28 @@ FtdiInterface::~FtdiInterface() { ftdi_deinit(&m_handle); } +std::string FtdiInterface::Description() const { + switch (m_interface) { + case INTERFACE_A: + return m_parent->Description() + " Port: 1"; + case INTERFACE_B: + return m_parent->Description() + " Port: 2"; + case INTERFACE_C: + return m_parent->Description() + " Port: 3"; + case INTERFACE_D: + return m_parent->Description() + " Port: 4"; + case INTERFACE_ANY: + return m_parent->Description(); + } + return m_parent->Description() + " Interface detection failure."; +} + + bool FtdiInterface::SetInterface() { OLA_INFO << "Setting interface to: " << m_interface; m_parent->setId(static_cast(m_interface)); if (ftdi_set_interface(&m_handle, m_interface) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -247,7 +264,7 @@ bool FtdiInterface::Open() { OLA_WARN << m_parent->Name() << " has no serial number, which might cause " << "issues with multiple devices"; if (ftdi_usb_open(&m_handle, m_parent->Vid(), m_parent->Pid()) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -260,7 +277,7 @@ bool FtdiInterface::Open() { if (ftdi_usb_open_desc(&m_handle, m_parent->Vid(), m_parent->Pid(), m_parent->Name().c_str(), m_parent->Serial().c_str()) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -271,7 +288,7 @@ bool FtdiInterface::Open() { bool FtdiInterface::Close() { if (ftdi_usb_close(&m_handle) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -285,7 +302,7 @@ bool FtdiInterface::IsOpen() const { bool FtdiInterface::Reset() { if (ftdi_usb_reset(&m_handle) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -295,7 +312,7 @@ bool FtdiInterface::Reset() { bool FtdiInterface::SetLineProperties() { if ((ftdi_set_line_property(&m_handle, BITS_8, STOP_BIT_2, NONE) < 0)) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -305,7 +322,7 @@ bool FtdiInterface::SetLineProperties() { bool FtdiInterface::SetBaudRate(int speed) { if (ftdi_set_baudrate(&m_handle, speed) < 0) { - OLA_WARN << "Error setting " << m_parent->Description() << " to baud rate " + OLA_WARN << "Error setting " << Description() << " to baud rate " << "of " << speed << " - " << ftdi_get_error_string(&m_handle); return false; } else { @@ -315,7 +332,7 @@ bool FtdiInterface::SetBaudRate(int speed) { bool FtdiInterface::SetFlowControl() { if (ftdi_setflowctrl(&m_handle, SIO_DISABLE_FLOW_CTRL) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -325,7 +342,7 @@ bool FtdiInterface::SetFlowControl() { bool FtdiInterface::ClearRts() { if (ftdi_setrts(&m_handle, 0) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -335,7 +352,7 @@ bool FtdiInterface::ClearRts() { bool FtdiInterface::PurgeBuffers() { if (ftdi_usb_purge_buffers(&m_handle) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -346,7 +363,7 @@ bool FtdiInterface::PurgeBuffers() { bool FtdiInterface::SetBreak(bool on) { if (ftdi_set_line_property2(&m_handle, BITS_8, STOP_BIT_2, NONE, (on ? BREAK_ON : BREAK_OFF)) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -361,7 +378,7 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { if(data.Size() >= 24) { packetBuffer.insert(1, data.GetRaw(), data.Size()); } else { - OLA_WARN << m_parent->Description() << " Broadcasting NULL DMX Package due to empty buffer."; + OLA_WARN << Description() << " Broadcasting NULL DMX Package due to empty buffer."; packetBuffer.append(512, '\x00'); } @@ -373,7 +390,7 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { data.Get(buffer + 1, &length); if (ftdi_write_data(&m_handle, buffer, length + 1) < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { @@ -396,12 +413,12 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { if (bytesWritten > 0 && m_echoState != OFF) { unsigned char readBuffer[bytesWritten]; int read = ftdi_read_data(&m_handle, readBuffer, bytesWritten); - OLA_DEBUG << m_parent->Description() + OLA_DEBUG << Description() << "Write() - Wrote: " << bytesWritten << " Read: " << read; } if (bytesWritten < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); return false; } else if (bytesWritten != static_cast(packet->size())) { @@ -417,7 +434,7 @@ int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); OLA_DEBUG << "ftdi_read_data() read: " << read; if (read < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); } return read; @@ -430,7 +447,7 @@ void FtdiInterface::DetectEchoState() { int bytesWritten = ftdi_write_data(&m_handle, testPattern, size); if (bytesWritten < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); m_echoState = UNKNOWN; return; @@ -441,10 +458,10 @@ void FtdiInterface::DetectEchoState() { } int bytesRead = ftdi_read_data(&m_handle, readBuffer, bytesWritten); if(bytesRead == 0) { - OLA_INFO << m_parent->Description() << " No data read, echo state OFF."; + OLA_INFO << Description() << " No data read, echo state OFF."; m_echoState = OFF; } else if(bytesRead < 0) { - OLA_WARN << m_parent->Description() << " " + OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle) << "\n" << "Echo state UNKNOWN"; m_echoState = UNKNOWN; @@ -453,14 +470,14 @@ void FtdiInterface::DetectEchoState() { for (int i = 0; i < bytesRead; i++) { if(testPattern[i] != readBuffer[i]) { m_echoState = UNKNOWN; - OLA_WARN << m_parent->Description() + OLA_WARN << Description() << " Mismatch in read data and test pattern, " << "echo state remains UNKNOWN."; return; } } } - OLA_INFO << m_parent->Description() << " Echo state ON."; + OLA_INFO << Description() << " Echo state ON."; m_echoState = ON; } diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 2abab83d4f..4d537afed4 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -156,7 +156,7 @@ class FtdiWidget { void setId(uint32_t id) { m_id = id; } std::string Description() const { - return m_name + " serial: " + m_serial + " port: " + std::to_string(m_id); + return m_name + " serial: " + m_serial; } /** @brief Get Widget available interface count **/ @@ -195,9 +195,7 @@ class FtdiInterface { virtual ~FtdiInterface(); - std::string Description() const { - return m_parent->Description(); - } + std::string Description() const; /** @brief Pick interface on multiport widgets */ bool SetInterface(); From bfc14db1eaf4dc4289f437e2d725b498107559a5 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 30 Jul 2019 01:07:38 +0300 Subject: [PATCH 75/86] Now works regardless of echo state and biasing resistors. TODO: Update docs and run through valgrind. --- plugins/ftdidmx/FtdiWidget.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 09487cf297..63e319600f 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -376,26 +376,12 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { packetBuffer[0] = DMX512_START_CODE; if(data.Size() >= 24) { - packetBuffer.insert(1, data.GetRaw(), data.Size()); + packetBuffer.append(data.GetRaw(), data.Size()); } else { - OLA_WARN << Description() << " Broadcasting NULL DMX Package due to empty buffer."; packetBuffer.append(512, '\x00'); } return Write(&packetBuffer); -/* unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; - unsigned int length = DMX_UNIVERSE_SIZE; - buffer[0] = DMX512_START_CODE; - - data.Get(buffer + 1, &length); - - if (ftdi_write_data(&m_handle, buffer, length + 1) < 0) { - OLA_WARN << Description() << " " - << ftdi_get_error_string(&m_handle); - return false; - } else { - return true; - }*/ } @@ -411,10 +397,8 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { * put on the line so that read will start at point of reception. */ if (bytesWritten > 0 && m_echoState != OFF) { - unsigned char readBuffer[bytesWritten]; - int read = ftdi_read_data(&m_handle, readBuffer, bytesWritten); - OLA_DEBUG << Description() - << "Write() - Wrote: " << bytesWritten << " Read: " << read; + unsigned char readBuffer[bytesWritten+1]; + ftdi_read_data(&m_handle, readBuffer, bytesWritten+1); } if (bytesWritten < 0) { @@ -432,7 +416,9 @@ bool FtdiInterface::Write(ola::io::ByteString *packet) { int FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); - OLA_DEBUG << "ftdi_read_data() read: " << read; + + OLA_DEBUG << Description() << "Read: " << read; + if (read < 0) { OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle); From 48d1dbed096c1eaa754bd96b5ef0449454657851 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 30 Jul 2019 01:26:48 +0300 Subject: [PATCH 76/86] Updated docs to reflect state of driver. Valgrind results suggests no leak in plugin, however there do seem to be leaks in RDM Core. --- plugins/ftdidmx/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/ftdidmx/README.md b/plugins/ftdidmx/README.md index 2d567e6529..93ad42ed01 100644 --- a/plugins/ftdidmx/README.md +++ b/plugins/ftdidmx/README.md @@ -14,7 +14,14 @@ At this stage we can't guarantee that the plugin meets all timing specs since I don't have any faulty RDM equipment to test with. It has however been tested with multiple responders on the line and discovery works correctly. -*It is also critical that the FTDI local echo function is disabled* +Ideally FTDI local echo should be disabled to prevent transimitted data from +being read. +The driver does have echo detection and attempts to correct for it, however +we can't commit to this working 100% off the time and it will add +unpredictability. + +The same applies for line biasing, things do seem to work without it but we +don't recommend it. ### Proper Line Biasing For simple DMX output (and input) all that is needed is a 130 Ohm resistor From a198e636459a90d24637300598185b41abce4bf9 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Tue, 30 Jul 2019 11:28:56 +0300 Subject: [PATCH 77/86] Fix some Travis spellintian issues --- plugins/ftdidmx/FtdiDmxThread.cpp | 2 +- plugins/ftdidmx/FtdiDmxThread.h | 2 +- plugins/ftdidmx/FtdiWidget.cpp | 10 +++++----- plugins/ftdidmx/FtdiWidget.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/ftdidmx/FtdiDmxThread.cpp b/plugins/ftdidmx/FtdiDmxThread.cpp index dcdce8cf9f..4f5ccbb3a0 100644 --- a/plugins/ftdidmx/FtdiDmxThread.cpp +++ b/plugins/ftdidmx/FtdiDmxThread.cpp @@ -158,7 +158,7 @@ void FtdiDmxThread::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, /** * @brief Method called to cleanup any outstanding callbacks - * @param state state to return to caller when possible. + * @param state to return to caller when possible. * * @note All callbacks except the RDMCallback lack a way of reporting an error * state to the caller. diff --git a/plugins/ftdidmx/FtdiDmxThread.h b/plugins/ftdidmx/FtdiDmxThread.h index 22eb2c53e7..f1ed438abc 100644 --- a/plugins/ftdidmx/FtdiDmxThread.h +++ b/plugins/ftdidmx/FtdiDmxThread.h @@ -103,7 +103,7 @@ class FtdiDmxThread const ola::rdm::UIDSet &uids); /** * @brief Method called to cleanup any outstanding callbacks - * @param state state to return to caller when possible. + * @param state to return to caller when possible. * * @note All callbacks except the RDMCallback lack a way of reporting an * error state to the caller. diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 63e319600f..16de02713b 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -375,7 +375,7 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { ola::io::ByteString packetBuffer; packetBuffer[0] = DMX512_START_CODE; - if(data.Size() >= 24) { + if (data.Size() >= 24) { packetBuffer.append(data.GetRaw(), data.Size()); } else { packetBuffer.append(512, '\x00'); @@ -443,18 +443,18 @@ void FtdiInterface::DetectEchoState() { << " Attempting detection of what was written."; } int bytesRead = ftdi_read_data(&m_handle, readBuffer, bytesWritten); - if(bytesRead == 0) { + if (bytesRead == 0) { OLA_INFO << Description() << " No data read, echo state OFF."; m_echoState = OFF; - } else if(bytesRead < 0) { + } else if (bytesRead < 0) { OLA_WARN << Description() << " " << ftdi_get_error_string(&m_handle) << "\n" << "Echo state UNKNOWN"; m_echoState = UNKNOWN; return; - } else if(bytesRead <= bytesWritten) { + } else if (bytesRead <= bytesWritten) { for (int i = 0; i < bytesRead; i++) { - if(testPattern[i] != readBuffer[i]) { + if (testPattern[i] != readBuffer[i]) { m_echoState = UNKNOWN; OLA_WARN << Description() << " Mismatch in read data and test pattern, " diff --git a/plugins/ftdidmx/FtdiWidget.h b/plugins/ftdidmx/FtdiWidget.h index 4d537afed4..51be556a5b 100644 --- a/plugins/ftdidmx/FtdiWidget.h +++ b/plugins/ftdidmx/FtdiWidget.h @@ -128,7 +128,7 @@ class FtdiWidget { * @brief Construct a new FtdiWidget instance for one widget. * @param serial The widget's USB serial number * @param name The widget's USB name (description) - * @param id id based on order of adding it seems from the code + * @param id based on order of adding it seems from the code * @param vid The VendorID of the device, def = FtdiWidgetInfo::ftdi_vid * @param pid The ProductID of the device, def = FtdiWidgetInfo::ft232_pid */ From e80f64d35ee0348882e5e3124d336228b55699f5 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 02:23:09 +0300 Subject: [PATCH 78/86] Pad packets smaller then 24 slots to 24 slots, if forced to send out null packets also with only 24 slots of data. --- plugins/ftdidmx/FtdiWidget.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/ftdidmx/FtdiWidget.cpp b/plugins/ftdidmx/FtdiWidget.cpp index 16de02713b..8287b0fbaf 100644 --- a/plugins/ftdidmx/FtdiWidget.cpp +++ b/plugins/ftdidmx/FtdiWidget.cpp @@ -375,10 +375,13 @@ bool FtdiInterface::Write(const ola::DmxBuffer& data) { ola::io::ByteString packetBuffer; packetBuffer[0] = DMX512_START_CODE; - if (data.Size() >= 24) { + if (data.Size() > 0) { packetBuffer.append(data.GetRaw(), data.Size()); + if (data.Size() < 24) { + packetBuffer.append(24 - data.Size(), '\x00'); + } } else { - packetBuffer.append(512, '\x00'); + packetBuffer.append(24, '\x00'); } return Write(&packetBuffer); From 011f591fb64e19317b4d5264ac4f62a4338d8962 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 02:29:05 +0300 Subject: [PATCH 79/86] Fix spelling errors found by 'codespell' Travis-CI check. --- common/utils/DmxBufferTest.cpp | 2 +- include/ola/web/JsonLexer.h | 20 ++++++++++---------- libs/acn/DMPInflatorTest.cpp | 2 +- libs/acn/E131InflatorTest.cpp | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/utils/DmxBufferTest.cpp b/common/utils/DmxBufferTest.cpp index 5596ce14a2..565d8bc779 100644 --- a/common/utils/DmxBufferTest.cpp +++ b/common/utils/DmxBufferTest.cpp @@ -196,7 +196,7 @@ void DmxBufferTest::testAssign() { // assigning to ourself does nothing buffer = buffer; - // assinging to a previously init'ed buffer + // assigning to a previously init'ed buffer unsigned int size = result_length; assignment_buffer = buffer; assignment_buffer.Get(result, &size); diff --git a/include/ola/web/JsonLexer.h b/include/ola/web/JsonLexer.h index 3e6455cac2..88fd7bbad7 100644 --- a/include/ola/web/JsonLexer.h +++ b/include/ola/web/JsonLexer.h @@ -84,34 +84,34 @@ class JsonParserInterface { virtual void End() = 0; /** - * @brief Called when a string is encounted. + * @brief Called when a string is encountered. * * This is not called for object keys, see ObjectKey() below. */ virtual void String(const std::string &value) = 0; /** - * @brief Called when a uint32_t is encounted. + * @brief Called when a uint32_t is encountered. */ virtual void Number(uint32_t value) = 0; /** - * @brief Called when a int32_t is encounted. + * @brief Called when a int32_t is encountered. */ virtual void Number(int32_t value) = 0; /** - * @brief Called when a uint64_t is encounted. + * @brief Called when a uint64_t is encountered. */ virtual void Number(uint64_t value) = 0; /** - * @brief Called when a int64_t is encounted. + * @brief Called when a int64_t is encountered. */ virtual void Number(int64_t value) = 0; /** - * @brief Called when a double value is encounted. + * @brief Called when a double value is encountered. * * MinGW struggles with long doubles * http://mingw.5.n7.nabble.com/Strange-behaviour-of-gcc-4-8-1-with-long-double-td32949.html @@ -121,17 +121,17 @@ class JsonParserInterface { virtual void Number(const JsonDouble::DoubleRepresentation &rep) = 0; /** - * @brief Called when a double value is encounted. + * @brief Called when a double value is encountered. */ virtual void Number(double d) = 0; /** - * @brief Called when a bool is encounted. + * @brief Called when a bool is encountered. */ virtual void Bool(bool value) = 0; /** - * @brief Called when a null token is encounted. + * @brief Called when a null token is encountered. */ virtual void Null() = 0; @@ -151,7 +151,7 @@ class JsonParserInterface { virtual void OpenObject() = 0; /** - * @brief Called when a new key is encounted. + * @brief Called when a new key is encountered. * * This may be called multiple times for the same object. The standard * doesn't specify how to handle duplicate keys, so I generally use the last diff --git a/libs/acn/DMPInflatorTest.cpp b/libs/acn/DMPInflatorTest.cpp index b4148fd185..cc08000ccc 100644 --- a/libs/acn/DMPInflatorTest.cpp +++ b/libs/acn/DMPInflatorTest.cpp @@ -70,7 +70,7 @@ void DMPInflatorTest::testDecodeHeader() { &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); - // test inherting the header from the prev call + // test inheriting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetDMPHeader(); diff --git a/libs/acn/E131InflatorTest.cpp b/libs/acn/E131InflatorTest.cpp index 54ef582b7c..f4f6435982 100644 --- a/libs/acn/E131InflatorTest.cpp +++ b/libs/acn/E131InflatorTest.cpp @@ -88,7 +88,7 @@ void E131InflatorTest::testDecodeRev2Header() { &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); - // test inherting the header from the prev call + // test inheriting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetE131Header(); @@ -136,7 +136,7 @@ void E131InflatorTest::testDecodeHeader() { &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); - // test inherting the header from the prev call + // test inheriting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetE131Header(); From b1dc145118a51b57611b4259c81ffe658673f25d Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 04:10:53 +0300 Subject: [PATCH 80/86] Added FtdiDmxPluginDescription.h to lint test blacklist and moved said list into variable. Also one spelling correction I missed. --- .travis-ci.sh | 23 +++++++++++++++-------- libs/acn/E133InflatorTest.cpp | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 466503673f..4805857477 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -11,6 +11,19 @@ COVERITY_SCAN_BUILD_URL="https://scan.coverity.com/scripts/travisci_build_coveri PYCHECKER_BLACKLIST="threading,unittest,cmd,optparse,google,google.protobuf,ssl,fftpack,lapack_lite,mtrand" +LINT_BLACKLIST=$(cat < Date: Fri, 2 Aug 2019 11:34:30 +0300 Subject: [PATCH 81/86] lint file search expression fixed? --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 4805857477..8c3e679242 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -87,7 +87,7 @@ if [[ $TASK = 'lint' ]]; then ./cpplint.py \ --filter=-legal/copyright,-readability/streams,-runtime/arrays \ $(find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( \ - $LINT_BLACKLIST + "$LINT_BLACKLIST" \) | xargs) if [[ $? -ne 0 ]]; then exit 1; From 4566ff89a8d4cff8824ae2e414885bb0f67859b7 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 12:08:59 +0300 Subject: [PATCH 82/86] lint find statement fixed --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 8c3e679242..322e60686c 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -87,7 +87,7 @@ if [[ $TASK = 'lint' ]]; then ./cpplint.py \ --filter=-legal/copyright,-readability/streams,-runtime/arrays \ $(find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( \ - "$LINT_BLACKLIST" + $LINT_BLACKLIST \ \) | xargs) if [[ $? -ne 0 ]]; then exit 1; From c85f0659814d4dd024f7c91921a358b956318b44 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 13:02:11 +0300 Subject: [PATCH 83/86] lint find statement --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 322e60686c..1c52b48d84 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -87,7 +87,7 @@ if [[ $TASK = 'lint' ]]; then ./cpplint.py \ --filter=-legal/copyright,-readability/streams,-runtime/arrays \ $(find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( \ - $LINT_BLACKLIST \ + "$LINT_BLACKLIST" \ \) | xargs) if [[ $? -ne 0 ]]; then exit 1; From e48cebd7a07820dbf977fa9d5d60382af2988372 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 13:18:25 +0300 Subject: [PATCH 84/86] Another attempt for lint files --- .travis-ci.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 1c52b48d84..9e3f3d0f16 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -82,13 +82,12 @@ if [[ $TASK = 'lint' ]]; then echo "Found $nolints generic NOLINTs" fi; # then fetch and run the main cpplint tool + lintfiles=`find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( $LINT_BLACKLIST \) | xargs)` wget -O cpplint.py $CPP_LINT_URL; chmod u+x cpplint.py; ./cpplint.py \ --filter=-legal/copyright,-readability/streams,-runtime/arrays \ - $(find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( \ - "$LINT_BLACKLIST" \ - \) | xargs) + $lintfiles if [[ $? -ne 0 ]]; then exit 1; fi; From 14a4513019225428802df40e23e3ea8b4a9516fa Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 13:59:26 +0300 Subject: [PATCH 85/86] fix wrong bracket in lint --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 9e3f3d0f16..5c16f3800d 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -82,7 +82,7 @@ if [[ $TASK = 'lint' ]]; then echo "Found $nolints generic NOLINTs" fi; # then fetch and run the main cpplint tool - lintfiles=`find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( $LINT_BLACKLIST \) | xargs)` + lintfiles=`find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( $LINT_BLACKLIST \) | xargs` wget -O cpplint.py $CPP_LINT_URL; chmod u+x cpplint.py; ./cpplint.py \ From 117f8316e415569a40837f11dd827a5649b20968 Mon Sep 17 00:00:00 2001 From: "E.S. Rosenberg a.k.a. Keeper of the Keys" Date: Fri, 2 Aug 2019 14:39:21 +0300 Subject: [PATCH 86/86] Another attempt --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 5c16f3800d..67e2e6139b 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -82,7 +82,7 @@ if [[ $TASK = 'lint' ]]; then echo "Found $nolints generic NOLINTs" fi; # then fetch and run the main cpplint tool - lintfiles=`find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( $LINT_BLACKLIST \) | xargs` + lintfiles=$(eval "find ./ \( -name "*.h" -or -name "*.cpp" \) -and ! \( $LINT_BLACKLIST \) | xargs") wget -O cpplint.py $CPP_LINT_URL; chmod u+x cpplint.py; ./cpplint.py \