The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
9.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. /**
  18. Parses data packets from a BLOCKS device, and translates them into callbacks
  19. on a handler object
  20. */
  21. template <typename Handler>
  22. struct HostPacketDecoder
  23. {
  24. static void processNextPacket (Handler& handler, TopologyIndex deviceIndex, const void* data, int size)
  25. {
  26. if (Packed7BitArrayReader::checksumIsOK (static_cast<const uint8*> (data), (uint32) size))
  27. {
  28. Packed7BitArrayReader reader (data, size - 1);
  29. if (reader.getRemainingBits() < (int) PacketTimestamp::bits)
  30. {
  31. jassertfalse; // not a valid message..
  32. return;
  33. }
  34. auto packetTimestamp = reader.read<PacketTimestamp>();
  35. deviceIndex &= 63; // top bit is used as a direction indicator
  36. while (processNextMessage (handler, reader, deviceIndex, packetTimestamp))
  37. {}
  38. }
  39. }
  40. static bool processNextMessage (Handler& handler, Packed7BitArrayReader& reader,
  41. TopologyIndex deviceIndex, PacketTimestamp packetTimestamp)
  42. {
  43. if (reader.getRemainingBits() < MessageType::bits)
  44. return false;
  45. auto messageType = reader.read<MessageType>().get();
  46. if (messageType == 0)
  47. return false;
  48. switch ((MessageFromDevice) messageType)
  49. {
  50. case MessageFromDevice::deviceTopology: return handleTopology (handler, reader);
  51. case MessageFromDevice::touchStart: return handleTouch (handler, reader, deviceIndex, packetTimestamp, true, false);
  52. case MessageFromDevice::touchMove: return handleTouch (handler, reader, deviceIndex, packetTimestamp, false, false);
  53. case MessageFromDevice::touchEnd: return handleTouch (handler, reader, deviceIndex, packetTimestamp, false, true);
  54. case MessageFromDevice::touchStartWithVelocity: return handleTouchWithVelocity (handler, reader, deviceIndex, packetTimestamp, true, false);
  55. case MessageFromDevice::touchMoveWithVelocity: return handleTouchWithVelocity (handler, reader, deviceIndex, packetTimestamp, false, false);
  56. case MessageFromDevice::touchEndWithVelocity: return handleTouchWithVelocity (handler, reader, deviceIndex, packetTimestamp, false, true);
  57. case MessageFromDevice::controlButtonDown: return handleButtonDownOrUp (handler, reader, deviceIndex, packetTimestamp, true);
  58. case MessageFromDevice::controlButtonUp: return handleButtonDownOrUp (handler, reader, deviceIndex, packetTimestamp, false);
  59. case MessageFromDevice::packetACK: return handlePacketACK (handler, reader, deviceIndex);
  60. default:
  61. jassertfalse; // got an invalid message type, could be a corrupt packet, or a
  62. // message type that the host doesn't expect to get
  63. return false;
  64. }
  65. }
  66. static bool handleTopology (Handler& handler, Packed7BitArrayReader& reader)
  67. {
  68. if (reader.getRemainingBits() < DeviceCount::bits + ConnectionCount::bits)
  69. {
  70. jassertfalse; // not enough data available for this message type!
  71. return false;
  72. }
  73. auto deviceProtocolVersion = reader.read<ProtocolVersion>();
  74. if (deviceProtocolVersion > currentProtocolVersion)
  75. {
  76. jassertfalse;
  77. return false;
  78. }
  79. const uint32 numDevices = reader.read<DeviceCount>();
  80. const uint32 numConnections = reader.read<ConnectionCount>();
  81. if ((uint32) reader.getRemainingBits() < numDevices * BitSizes::topologyDeviceInfo
  82. + numConnections * BitSizes::topologyConnectionInfo)
  83. {
  84. jassertfalse; // not enough data available for this message type!
  85. return false;
  86. }
  87. handler.beginTopology ((int) numDevices, (int) numConnections);
  88. for (uint32 i = 0; i < numDevices; ++i)
  89. handleTopologyDevice (handler, reader);
  90. for (uint32 i = 0; i < numConnections; ++i)
  91. handleTopologyConnection (handler, reader);
  92. handler.endTopology();
  93. return true;
  94. }
  95. static void handleTopologyDevice (Handler& handler, Packed7BitArrayReader& reader)
  96. {
  97. DeviceStatus status;
  98. for (uint32 i = 0; i < sizeof (BlockSerialNumber); ++i)
  99. status.serialNumber.serial[i] = (uint8) reader.readBits (7);
  100. status.index = (TopologyIndex) reader.readBits (topologyIndexBits);
  101. status.batteryLevel = reader.read<BatteryLevel>();
  102. status.batteryCharging = reader.read<BatteryCharging>();
  103. handler.handleTopologyDevice (status);
  104. }
  105. static void handleTopologyConnection (Handler& handler, Packed7BitArrayReader& reader)
  106. {
  107. DeviceConnection connection;
  108. connection.device1 = (uint8) reader.readBits (topologyIndexBits);
  109. connection.port1 = reader.read<ConnectorPort>();
  110. connection.device2 = (uint8) reader.readBits (topologyIndexBits);
  111. connection.port2 = reader.read<ConnectorPort>();
  112. handler.handleTopologyConnection (connection);
  113. }
  114. static bool handleTouch (Handler& handler, Packed7BitArrayReader& reader, TopologyIndex deviceIndex,
  115. PacketTimestamp packetTimestamp, bool isStart, bool isEnd)
  116. {
  117. if (reader.getRemainingBits() < BitSizes::touchMessage - MessageType::bits)
  118. {
  119. jassertfalse; // not enough data available for this message type!
  120. return false;
  121. }
  122. auto timeOffset = reader.read<PacketTimestampOffset>();
  123. auto touchIndex = reader.read<TouchIndex>();
  124. auto x = reader.read<TouchPosition::Xcoord>();
  125. auto y = reader.read<TouchPosition::Ycoord>();
  126. auto z = reader.read<TouchPosition::Zcoord>();
  127. handleTouch (handler, deviceIndex, packetTimestamp.get() + timeOffset.get(),
  128. touchIndex, { x, y, z }, { 0, 0, 0 }, isStart, isEnd);
  129. return true;
  130. }
  131. static bool handleTouchWithVelocity (Handler& handler, Packed7BitArrayReader& reader, TopologyIndex deviceIndex,
  132. PacketTimestamp packetTimestamp, bool isStart, bool isEnd)
  133. {
  134. if (reader.getRemainingBits() < BitSizes::touchMessageWithVelocity - MessageType::bits)
  135. {
  136. jassertfalse; // not enough data available for this message type!
  137. return false;
  138. }
  139. auto timeOffset = reader.read<PacketTimestampOffset>();
  140. auto touchIndex = reader.read<TouchIndex>();
  141. auto x = reader.read<TouchPosition::Xcoord>();
  142. auto y = reader.read<TouchPosition::Ycoord>();
  143. auto z = reader.read<TouchPosition::Zcoord>();
  144. auto vx = reader.read<TouchVelocity::VXcoord>();
  145. auto vy = reader.read<TouchVelocity::VYcoord>();
  146. auto vz = reader.read<TouchVelocity::VZcoord>();
  147. handleTouch (handler, deviceIndex, packetTimestamp.get() + timeOffset.get(),
  148. touchIndex, { x, y, z }, { vx, vy, vz }, isStart, isEnd);
  149. return true;
  150. }
  151. static void handleTouch (Handler& handler, TopologyIndex deviceIndex, uint32 timestamp, TouchIndex touchIndex,
  152. TouchPosition position, TouchVelocity velocity, bool isStart, bool isEnd)
  153. {
  154. handler.handleTouchChange (deviceIndex, timestamp, touchIndex, position, velocity, isStart, isEnd);
  155. }
  156. static bool handleButtonDownOrUp (Handler& handler, Packed7BitArrayReader& reader, TopologyIndex deviceIndex,
  157. PacketTimestamp packetTimestamp, bool isDown)
  158. {
  159. if (reader.getRemainingBits() < BitSizes::controlButtonMessage - MessageType::bits)
  160. {
  161. jassertfalse; // not enough data available for this message type!
  162. return false;
  163. }
  164. auto timeOffset = reader.read<PacketTimestampOffset>();
  165. auto buttonID = reader.read<ControlButtonID>();
  166. handler.handleControlButtonUpDown (deviceIndex, packetTimestamp.get() + timeOffset.get(), buttonID, isDown);
  167. return true;
  168. }
  169. static bool handlePacketACK (Handler& handler, Packed7BitArrayReader& reader, TopologyIndex deviceIndex)
  170. {
  171. if (reader.getRemainingBits() < BitSizes::packetACK - MessageType::bits)
  172. {
  173. jassertfalse; // not enough data available for this message type!
  174. return false;
  175. }
  176. handler.handlePacketACK (deviceIndex, reader.read<PacketCounter>());
  177. return true;
  178. }
  179. };