diff -r 15d87fdd6e6c -r 334b727f7516 DJMFix.cpp --- a/DJMFix.cpp Mon Jan 04 15:45:12 2021 +0100 +++ b/DJMFix.cpp Mon Jan 04 17:11:57 2021 +0100 @@ -35,6 +35,8 @@ private: MidiSender* midiSender; djmfix::logging::Logger* logger; + const int keepAliveInterval = 200; + int keepAliveCounter = 0; std::thread keepAliveThread; std::recursive_mutex midiMutex; std::atomic running{false}; @@ -46,7 +48,9 @@ while (!stopped) { logger->log(L::FINE, "DJMFixImpl::run()"); if (sendKeepAlive) send({0xf0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x50, 0x01, 0xf7}); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(keepAliveInterval)); + keepAliveCounter++; + if (keepAliveCounter % (60 * 1000 / keepAliveInterval) == 0) logger->log(L::INFO, "Still sending periodic keep-alive messages (each " + std::to_string(keepAliveInterval) + " ms)."); } } @@ -62,7 +66,7 @@ } Bytes normalize(const Bytes& data) { - if (data.size() % 2) throw std::invalid_argument("data before normalization must have even number of bytes"); + if (data.size() % 2) throw std::invalid_argument("Data before normalization must have even number of bytes."); Bytes result; result.reserve(data.size() / 2); for (size_t i = 0; i < data.size() / 2; i++) result.push_back((data[i * 2] & 0x0F) << 4 | (data[i * 2 + 1] & 0x0F)); @@ -111,7 +115,7 @@ } template std::vector xOR(const std::vector& a, const std::vector& b) { - if (a.size() != b.size()) throw std::invalid_argument("xor: both must be the same length"); + if (a.size() != b.size()) throw std::invalid_argument("Both must be the same length when doing XOR."); std::vector result; result.reserve(a.size()); for (size_t i = 0; i < a.size(); i++) result.push_back(a[i] ^ b[i]); @@ -124,28 +128,30 @@ } virtual ~DJMFixImpl() override { - logger->log(L::FINE, "~DJMFixImpl()"); + logger->log(L::FINER, "~DJMFixImpl()"); if (running) stop(); } void setMidiSender(MidiSender* midiSender) { - logger->log(L::FINE, "DJMFixImpl::setMidiSender()"); + logger->log(L::FINER, "DJMFixImpl::setMidiSender()"); this->midiSender = midiSender; } virtual void receive(const MidiMessage& midiMessage) override { - logger->log(L::INFO, "received message: size = " + std::to_string(midiMessage.size()) + " data = " + toString(midiMessage)); + logger->log(L::FINE, "Received a message: size = " + std::to_string(midiMessage.size()) + " data = " + toString(midiMessage)); std::lock_guard lock(midiMutex); if (midiMessage.size() == 12 && midiMessage[9] == 0x11) { + logger->log(L::INFO, "Received greeting message."); send({0xf0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x12, 0x2a, 0x01, 0x0b, 0x50, 0x69, 0x6f, 0x6e, 0x65, 0x65, 0x72, 0x44, 0x4a, 0x02, 0x0b, 0x72, 0x65, 0x6b, 0x6f, 0x72, 0x64, 0x62, 0x6f, 0x78, 0x03, 0x12, 0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0xf7}); + logger->log(L::INFO, "Sent message with seed1."); } else if (midiMessage.size() == 54 && midiMessage[9] == 0x13 && midiMessage[33] == 0x04 && midiMessage[43] == 0x03) { Bytes hash1(midiMessage.begin() + 35, midiMessage.begin() + 35 + 8); seed2 = Bytes(midiMessage.begin() + 45, midiMessage.begin() + 45 + 8); hash1 = normalize(hash1); seed2 = normalize(seed2); - logger->log(L::INFO, "got message with hash1 = " + toString(hash1) + " and seed2 = " + toString(seed2)); + logger->log(L::INFO, "Received message with hash1 = " + toString(hash1) + " and seed2 = " + toString(seed2)); Bytes seed0 = {0x68, 0x01, 0x31, 0xFB}; Bytes seed1 = {0x29, 0x00, 0x00, 0x00, 0x23, 0x48, 0x00, 0x00}; @@ -153,13 +159,14 @@ Bytes hash1check = toBytes(fnv32hash(concat(seed1, xOR(seed0, seed2)))); if (equals(hash1, hash1check)) { - logger->log(L::INFO, "hash1 verification: OK"); + logger->log(L::INFO, "Verification of hash1 was successful."); Bytes hash2 = toBytes(fnv32hash(concat(seed2, xOR(seed0, seed2)))); send(concat({0xf0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x14, 0x38, 0x01, 0x0b, 0x50, 0x69, 0x6f, 0x6e, 0x65, 0x65, 0x72, 0x44, 0x4a, 0x02, 0x0b, 0x72, 0x65, 0x6b, 0x6f, 0x72, 0x64, 0x62, 0x6f, 0x78, 0x04, 0x0a}, concat(denormalize(hash2),{0x05, 0x16, 0x05, 0x09, 0x0b, 0x05, 0x04, 0x0b, 0x0f, 0x0e, 0x0e, 0x04, 0x04, 0x0a, 0x05, 0x0a, 0x0c, 0x08, 0x0e, 0x04, 0x0c, 0x05, 0xf7}))); + logger->log(L::INFO, "Sent message with hash2."); } else { std::stringstream logMessage; logMessage - << "hash1 verification failed: " + << "Verification of hash1 failed: " << " midiMessage = " << toString(midiMessage) << " seed0 = " << toString(seed0) << " seed1 = " << toString(seed1) @@ -171,16 +178,18 @@ } } else if (midiMessage.size() == 12 && midiMessage[9] == 0x15) { sendKeepAlive = true; + logger->log(L::INFO, "Received acknowledgment message. Started sending keep-alive messages. LINE/PHONO channels should work now."); } } void start() override { logger->log(L::FINE, "DJMFixImpl::start()"); - if (midiSender == nullptr) throw std::logic_error("need a midiSender when starting DJMFix"); + if (midiSender == nullptr) throw std::logic_error("Need a midiSender when starting DJMFix"); // TODO: methods for parsing and constructing messages from parts (TLV) send({0xf0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x50, 0x01, 0xf7}); + logger->log(L::INFO, "Sent greeting message."); keepAliveThread = std::thread(&DJMFixImpl::run, this); running = true;