branch | v_0 |
changeset 8 | 87dfa7c89294 |
parent 7 | 889b4b8737bd |
child 12 | 15d87fdd6e6c |
7:889b4b8737bd | 8:87dfa7c89294 |
---|---|
34 MidiSender* midiSender; |
34 MidiSender* midiSender; |
35 std::thread keepAliveThread; |
35 std::thread keepAliveThread; |
36 std::recursive_mutex midiMutex; |
36 std::recursive_mutex midiMutex; |
37 std::atomic<bool> running{false}; |
37 std::atomic<bool> running{false}; |
38 std::atomic<bool> stopped{false}; |
38 std::atomic<bool> stopped{false}; |
39 std::atomic<bool> sendKeepAlive{false}; |
|
40 Bytes seed2; |
|
39 |
41 |
40 void run() { |
42 void run() { |
41 while (!stopped) { |
43 while (!stopped) { |
42 std::cerr << "DJMFixImpl::run()" << std::endl; // TODO: do not mess STDIO |
44 std::cerr << "DJMFixImpl::run()" << std::endl; // TODO: do not mess STDIO |
43 // TODO: send keep-alive messages |
45 if (sendKeepAlive) send({0xf0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x50, 0x01, 0xf7}); |
44 std::this_thread::sleep_for(std::chrono::milliseconds(200)); |
46 std::this_thread::sleep_for(std::chrono::milliseconds(200)); |
45 } |
47 } |
46 } |
48 } |
47 |
49 |
48 void send(const MidiMessage& midiMessage) { |
50 void send(const MidiMessage& midiMessage) { |
59 Bytes normalize(const Bytes& data) { |
61 Bytes normalize(const Bytes& data) { |
60 if (data.size() % 2) throw std::invalid_argument("data before normalization must have even number of bytes"); |
62 if (data.size() % 2) throw std::invalid_argument("data before normalization must have even number of bytes"); |
61 Bytes result; |
63 Bytes result; |
62 result.reserve(data.size() / 2); |
64 result.reserve(data.size() / 2); |
63 for (size_t i = 0; i < data.size() / 2; i++) result.push_back((data[i * 2] & 0x0F) << 4 | (data[i * 2 + 1] & 0x0F)); |
65 for (size_t i = 0; i < data.size() / 2; i++) result.push_back((data[i * 2] & 0x0F) << 4 | (data[i * 2 + 1] & 0x0F)); |
66 return result; |
|
67 } |
|
68 |
|
69 Bytes denormalize(const Bytes& data) { |
|
70 Bytes result; |
|
71 result.reserve(data.size()*2); |
|
72 for (size_t i = 0; i < data.size(); i++) { |
|
73 result.push_back(data[i] >> 4); |
|
74 result.push_back(data[i] & 0x0F); |
|
75 } |
|
64 return result; |
76 return result; |
65 } |
77 } |
66 |
78 |
67 uint32_t fnv32hash(const Bytes& buff) { |
79 uint32_t fnv32hash(const Bytes& buff) { |
68 uint32_t hash = 0x811c9dc5; |
80 uint32_t hash = 0x811c9dc5; |
122 |
134 |
123 if (midiMessage.size() == 12 && midiMessage[9] == 0x11) { |
135 if (midiMessage.size() == 12 && midiMessage[9] == 0x11) { |
124 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}); |
136 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}); |
125 } else if (midiMessage.size() == 54 && midiMessage[9] == 0x13 && midiMessage[33] == 0x04 && midiMessage[43] == 0x03) { |
137 } else if (midiMessage.size() == 54 && midiMessage[9] == 0x13 && midiMessage[33] == 0x04 && midiMessage[43] == 0x03) { |
126 Bytes hash1(midiMessage.begin() + 35, midiMessage.begin() + 35 + 8); |
138 Bytes hash1(midiMessage.begin() + 35, midiMessage.begin() + 35 + 8); |
127 Bytes seed2(midiMessage.begin() + 45, midiMessage.begin() + 45 + 8); |
139 seed2 = Bytes(midiMessage.begin() + 45, midiMessage.begin() + 45 + 8); |
128 hash1 = normalize(hash1); |
140 hash1 = normalize(hash1); |
129 seed2 = normalize(seed2); |
141 seed2 = normalize(seed2); |
130 std::cerr << "DJMFixImpl::receive(): got message with hash1 = " << toString(hash1) << " and seed2 = " << toString(seed2) << std::endl; // TODO: do not mess STDIO |
142 std::cerr << "DJMFixImpl::receive(): got message with hash1 = " << toString(hash1) << " and seed2 = " << toString(seed2) << std::endl; // TODO: do not mess STDIO |
131 |
143 |
132 Bytes seed0 = {0x68, 0x01, 0x31, 0xFB}; |
144 Bytes seed0 = {0x68, 0x01, 0x31, 0xFB}; |
133 Bytes seed1 = {0x29, 0x00, 0x00, 0x00, 0x23, 0x48, 0x00, 0x00}; |
145 Bytes seed1 = {0x29, 0x00, 0x00, 0x00, 0x23, 0x48, 0x00, 0x00}; |
134 |
146 |
135 Bytes hash1check = toBytes(fnv32hash(concat(seed1, xOR(seed0, seed2)))); |
147 Bytes hash1check = toBytes(fnv32hash(concat(seed1, xOR(seed0, seed2)))); |
136 |
148 |
137 if (equals(hash1, hash1check)) { |
149 if (equals(hash1, hash1check)) { |
138 std::cerr << "DJMFixImpl::receive(): hash1 verification: OK" << std::endl; |
150 std::cerr << "DJMFixImpl::receive(): hash1 verification: OK" << std::endl; // TODO: do not mess STDIO |
151 Bytes hash2 = toBytes(fnv32hash(concat(seed2, xOR(seed0, seed2)))); |
|
152 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}))); |
|
139 } else { |
153 } else { |
140 std::cerr << "DJMFixImpl::receive(): hash1 verification: ERROR: check = " << toString(hash1check) << std::endl; |
154 std::cerr |
155 << "DJMFixImpl::receive(): hash1 verification failed: " |
|
156 << " midiMessage = " << toString(midiMessage) |
|
157 << " seed0 = " << toString(seed0) |
|
158 << " seed1 = " << toString(seed1) |
|
159 << " seed2 = " << toString(seed2) |
|
160 << " hash1 = " << toString(hash1) |
|
161 << " hash1check = " << toString(hash1check) |
|
162 << std::endl; |
|
163 // TODO: graceful death |
|
141 } |
164 } |
165 } else if (midiMessage.size() == 12 && midiMessage[9] == 0x15) { |
|
166 sendKeepAlive = true; |
|
142 } |
167 } |
143 |
168 |
144 } |
169 } |
145 |
170 |
146 void start() override { |
171 void start() override { |