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.

786 lines
26KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. namespace
  20. {
  21. static Block::Timestamp deviceTimestampToHost (uint32 timestamp) noexcept
  22. {
  23. return static_cast<Block::Timestamp> (timestamp);
  24. }
  25. }
  26. template <typename Detector>
  27. struct ConnectedDeviceGroup : private AsyncUpdater,
  28. private Timer
  29. {
  30. //==============================================================================
  31. ConnectedDeviceGroup (Detector& d, const String& name, PhysicalTopologySource::DeviceConnection* connection)
  32. : detector (d), deviceName (name), deviceConnection (connection)
  33. {
  34. if (auto midiDeviceConnection = static_cast<MIDIDeviceConnection*> (deviceConnection.get()))
  35. {
  36. ScopedLock lock (midiDeviceConnection->criticalSecton);
  37. setMidiMessageCallback();
  38. }
  39. else
  40. {
  41. setMidiMessageCallback();
  42. }
  43. initialiseSerialReader();
  44. startTimer (200);
  45. sendTopologyRequest();
  46. }
  47. ~ConnectedDeviceGroup() override
  48. {
  49. for (const auto& device : currentDeviceInfo)
  50. detector.handleDeviceRemoved (device);
  51. }
  52. bool isStillConnected (const StringArray& detectedDevices) const noexcept
  53. {
  54. return detectedDevices.contains (deviceName) && ! failedToGetTopology();
  55. }
  56. bool contains (Block::UID uid)
  57. {
  58. return getIndexFromDeviceID (uid) >= 0;
  59. }
  60. void handleBlockRestarting (Block::UID deviceID)
  61. {
  62. forceApiDisconnected (deviceID);
  63. }
  64. //==============================================================================
  65. // The following methods will be called by the HostPacketDecoder:
  66. void beginTopology (int numDevices, int numConnections)
  67. {
  68. incomingTopologyDevices.clearQuick();
  69. incomingTopologyDevices.ensureStorageAllocated (numDevices);
  70. incomingTopologyConnections.clearQuick();
  71. incomingTopologyConnections.ensureStorageAllocated (numConnections);
  72. }
  73. void extendTopology (int numDevices, int numConnections)
  74. {
  75. incomingTopologyDevices.ensureStorageAllocated (incomingTopologyDevices.size() + numDevices);
  76. incomingTopologyConnections.ensureStorageAllocated (incomingTopologyConnections.size() + numConnections);
  77. }
  78. void handleTopologyDevice (BlocksProtocol::DeviceStatus status)
  79. {
  80. incomingTopologyDevices.add (status);
  81. }
  82. void handleTopologyConnection (BlocksProtocol::DeviceConnection connection)
  83. {
  84. incomingTopologyConnections.add (connection);
  85. }
  86. void endTopology()
  87. {
  88. lastTopologyReceiveTime = Time::getCurrentTime();
  89. if (incomingTopologyDevices.isEmpty()
  90. || incomingTopologyConnections.size() < incomingTopologyDevices.size() - 1)
  91. {
  92. LOG_CONNECTIVITY ("Invalid topology or device list received.");
  93. LOG_CONNECTIVITY ("Device size : " << incomingTopologyDevices.size());
  94. LOG_CONNECTIVITY ("Connections size : " << incomingTopologyConnections.size());
  95. scheduleNewTopologyRequest();
  96. return;
  97. }
  98. LOG_CONNECTIVITY ("Valid topology received");
  99. updateCurrentDeviceList();
  100. updateCurrentDeviceConnections();
  101. }
  102. void handleVersion (BlocksProtocol::DeviceVersion version)
  103. {
  104. setVersion (version.index, version.version);
  105. }
  106. void handleName (BlocksProtocol::DeviceName name)
  107. {
  108. if (name.name.length <= 1)
  109. return;
  110. if (const auto info = getDeviceInfoFromIndex (name.index))
  111. {
  112. if (info->name == name.name)
  113. return;
  114. info->name = name.name;
  115. detector.handleDeviceUpdated (*info);
  116. }
  117. }
  118. void handleControlButtonUpDown (BlocksProtocol::TopologyIndex deviceIndex, uint32 timestamp,
  119. BlocksProtocol::ControlButtonID buttonID, bool isDown)
  120. {
  121. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  122. detector.handleButtonChange (deviceID, deviceTimestampToHost (timestamp), buttonID.get(), isDown);
  123. }
  124. void handleCustomMessage (BlocksProtocol::TopologyIndex deviceIndex, uint32 timestamp, const int32* data)
  125. {
  126. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  127. detector.handleCustomMessage (deviceID, deviceTimestampToHost (timestamp), data);
  128. }
  129. void handleTouchChange (BlocksProtocol::TopologyIndex deviceIndex,
  130. uint32 timestamp,
  131. BlocksProtocol::TouchIndex touchIndex,
  132. BlocksProtocol::TouchPosition position,
  133. BlocksProtocol::TouchVelocity velocity,
  134. bool isStart, bool isEnd)
  135. {
  136. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  137. {
  138. TouchSurface::Touch touch;
  139. touch.index = (int) touchIndex.get();
  140. touch.x = (float) position.x.toUnipolarFloat();
  141. touch.y = (float) position.y.toUnipolarFloat();
  142. touch.z = (float) position.z.toUnipolarFloat();
  143. touch.xVelocity = velocity.vx.toBipolarFloat();
  144. touch.yVelocity = velocity.vy.toBipolarFloat();
  145. touch.zVelocity = velocity.vz.toBipolarFloat();
  146. touch.eventTimestamp = deviceTimestampToHost (timestamp);
  147. touch.isTouchStart = isStart;
  148. touch.isTouchEnd = isEnd;
  149. touch.blockUID = deviceID;
  150. setTouchStartPosition (touch);
  151. detector.handleTouchChange (deviceID, touch);
  152. }
  153. }
  154. void setTouchStartPosition (TouchSurface::Touch& touch)
  155. {
  156. auto& startPos = touchStartPositions.getValue (touch);
  157. if (touch.isTouchStart)
  158. startPos = { touch.x, touch.y };
  159. touch.startX = startPos.x;
  160. touch.startY = startPos.y;
  161. }
  162. void handlePacketACK (BlocksProtocol::TopologyIndex deviceIndex,
  163. BlocksProtocol::PacketCounter counter)
  164. {
  165. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  166. {
  167. detector.handleSharedDataACK (deviceID, counter);
  168. updateApiPing (deviceID);
  169. }
  170. }
  171. void handleFirmwareUpdateACK (BlocksProtocol::TopologyIndex deviceIndex,
  172. BlocksProtocol::FirmwareUpdateACKCode resultCode,
  173. BlocksProtocol::FirmwareUpdateACKDetail resultDetail)
  174. {
  175. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  176. {
  177. detector.handleFirmwareUpdateACK (deviceID, (uint8) resultCode.get(), (uint32) resultDetail.get());
  178. updateApiPing (deviceID);
  179. }
  180. }
  181. void handleConfigUpdateMessage (BlocksProtocol::TopologyIndex deviceIndex,
  182. int32 item, int32 value, int32 min, int32 max)
  183. {
  184. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  185. detector.handleConfigUpdateMessage (deviceID, item, value, min, max);
  186. }
  187. void handleConfigSetMessage (BlocksProtocol::TopologyIndex deviceIndex,
  188. int32 item, int32 value)
  189. {
  190. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  191. detector.handleConfigSetMessage (deviceID, item, value);
  192. }
  193. void handleConfigFactorySyncEndMessage (BlocksProtocol::TopologyIndex deviceIndex)
  194. {
  195. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  196. detector.handleConfigFactorySyncEndMessage (deviceID);
  197. }
  198. void handleConfigFactorySyncResetMessage (BlocksProtocol::TopologyIndex deviceIndex)
  199. {
  200. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  201. detector.handleConfigFactorySyncResetMessage (deviceID);
  202. }
  203. void handleLogMessage (BlocksProtocol::TopologyIndex deviceIndex, const String& message)
  204. {
  205. if (auto deviceID = getDeviceIDFromIndex (deviceIndex))
  206. detector.handleLogMessage (deviceID, message);
  207. }
  208. //==============================================================================
  209. template <typename PacketBuilder>
  210. bool sendMessageToDevice (const PacketBuilder& builder) const
  211. {
  212. if (deviceConnection->sendMessageToDevice (builder.getData(), (size_t) builder.size()))
  213. {
  214. #if DUMP_BANDWIDTH_STATS
  215. registerBytesOut (builder.size());
  216. #endif
  217. return true;
  218. }
  219. return false;
  220. }
  221. PhysicalTopologySource::DeviceConnection* getDeviceConnection()
  222. {
  223. return deviceConnection.get();
  224. }
  225. Array<BlockDeviceConnection> getCurrentDeviceConnections()
  226. {
  227. Array<BlockDeviceConnection> connections;
  228. for (const auto& connection : currentDeviceConnections)
  229. if (isApiConnected (getDeviceIDFromIndex (connection.device1)) && isApiConnected (getDeviceIDFromIndex (connection.device2)))
  230. connections.add (getBlockDeviceConnection (connection));
  231. return connections;
  232. }
  233. Detector& detector;
  234. String deviceName;
  235. static constexpr double pingTimeoutSeconds = 6.0;
  236. private:
  237. //==============================================================================
  238. Array<DeviceInfo> currentDeviceInfo;
  239. Array<BlocksProtocol::DeviceStatus> incomingTopologyDevices;
  240. Array<BlocksProtocol::DeviceConnection> incomingTopologyConnections, currentDeviceConnections;
  241. std::unique_ptr<PhysicalTopologySource::DeviceConnection> deviceConnection;
  242. CriticalSection incomingPacketLock;
  243. Array<MemoryBlock> incomingPackets;
  244. std::unique_ptr<DepreciatedVersionReader> depreciatedVersionReader;
  245. std::unique_ptr<BlockSerialReader> masterSerialReader;
  246. struct TouchStart { float x, y; };
  247. TouchList<TouchStart> touchStartPositions;
  248. static constexpr Block::UID invalidUid = 0;
  249. Block::UID masterBlockUid = invalidUid;
  250. //==============================================================================
  251. void timerCallback() override
  252. {
  253. const auto now = Time::getCurrentTime();
  254. if ((now > lastTopologyReceiveTime + RelativeTime::seconds (30.0))
  255. && now > lastTopologyRequestTime + RelativeTime::seconds (1.0)
  256. && numTopologyRequestsSent < 4)
  257. sendTopologyRequest();
  258. checkApiTimeouts (now);
  259. startApiModeOnConnectedBlocks();
  260. checkMasterBlockVersion();
  261. checkMasterSerial();
  262. }
  263. //==============================================================================
  264. void setMidiMessageCallback()
  265. {
  266. deviceConnection->handleMessageFromDevice = [this] (const void* data, size_t dataSize)
  267. {
  268. this->handleIncomingMessage (data, dataSize);
  269. };
  270. }
  271. void handleIncomingMessage (const void* data, size_t dataSize)
  272. {
  273. MemoryBlock mb (data, dataSize);
  274. {
  275. const ScopedLock sl (incomingPacketLock);
  276. incomingPackets.add (std::move (mb));
  277. }
  278. triggerAsyncUpdate();
  279. #if DUMP_BANDWIDTH_STATS
  280. registerBytesIn ((int) dataSize);
  281. #endif
  282. }
  283. void handleAsyncUpdate() override
  284. {
  285. Array<MemoryBlock> packets;
  286. packets.ensureStorageAllocated (32);
  287. {
  288. const ScopedLock sl (incomingPacketLock);
  289. incomingPackets.swapWith (packets);
  290. }
  291. for (auto& packet : packets)
  292. {
  293. auto data = static_cast<const uint8*> (packet.getData());
  294. BlocksProtocol::HostPacketDecoder<ConnectedDeviceGroup>
  295. ::processNextPacket (*this, *data, data + 1, (int) packet.getSize() - 1);
  296. }
  297. }
  298. bool sendCommandMessage (BlocksProtocol::TopologyIndex deviceIndex, uint32 commandID) const
  299. {
  300. BlocksProtocol::HostPacketBuilder<64> p;
  301. p.writePacketSysexHeaderBytes (deviceIndex);
  302. p.deviceControlMessage (commandID);
  303. p.writePacketSysexFooter();
  304. return sendMessageToDevice (p);
  305. }
  306. //==============================================================================
  307. Time lastTopologyRequestTime, lastTopologyReceiveTime;
  308. int numTopologyRequestsSent = 0;
  309. void scheduleNewTopologyRequest()
  310. {
  311. LOG_CONNECTIVITY ("Topology Request Scheduled");
  312. numTopologyRequestsSent = 0;
  313. lastTopologyReceiveTime = Time();
  314. lastTopologyRequestTime = Time::getCurrentTime();
  315. }
  316. void sendTopologyRequest()
  317. {
  318. ++numTopologyRequestsSent;
  319. lastTopologyRequestTime = Time::getCurrentTime();
  320. sendCommandMessage (0, BlocksProtocol::requestTopologyMessage);
  321. }
  322. bool failedToGetTopology() const noexcept
  323. {
  324. return numTopologyRequestsSent >= 4 && lastTopologyReceiveTime == Time();
  325. }
  326. //==============================================================================
  327. void checkMasterBlockVersion()
  328. {
  329. if (depreciatedVersionReader == nullptr)
  330. return;
  331. const auto masterVersion = depreciatedVersionReader->getVersionNumber();
  332. if (masterVersion.isNotEmpty())
  333. {
  334. const auto masterIndex = getIndexFromDeviceID (masterBlockUid);
  335. if (masterIndex >= 0)
  336. setVersion (BlocksProtocol::TopologyIndex (masterIndex), masterVersion);
  337. else
  338. jassertfalse;
  339. }
  340. }
  341. void setVersion (const BlocksProtocol::TopologyIndex index, const BlocksProtocol::VersionNumber versionNumber)
  342. {
  343. if (versionNumber.length <= 1)
  344. return;
  345. if (const auto info = getDeviceInfoFromIndex (index))
  346. {
  347. if (info->version == versionNumber)
  348. return;
  349. if (info->uid == masterBlockUid)
  350. depreciatedVersionReader.reset();
  351. info->version = versionNumber;
  352. detector.handleDeviceUpdated (*info);
  353. }
  354. }
  355. //==============================================================================
  356. void checkMasterSerial()
  357. {
  358. if (masterSerialReader == nullptr)
  359. initialiseSerialReader();
  360. if (masterSerialReader == nullptr)
  361. return;
  362. if (masterBlockUid != invalidUid && masterSerialReader->hasSerial())
  363. {
  364. auto uid = getBlockUIDFromSerialNumber (masterSerialReader->getSerial());
  365. if (uid != masterBlockUid)
  366. updateMasterUid (uid);
  367. }
  368. }
  369. void updateMasterUid (const Block::UID newMasterUid)
  370. {
  371. LOG_CONNECTIVITY ("Updating master from " + String (masterBlockUid) + " to " + String (newMasterUid));
  372. masterBlockUid = newMasterUid;
  373. Array<DeviceInfo> devicesToUpdate;
  374. for (auto& info : currentDeviceInfo)
  375. {
  376. if (info.masterUid != masterBlockUid)
  377. {
  378. info.masterUid = masterBlockUid;
  379. info.isMaster = info.uid == masterBlockUid;
  380. devicesToUpdate.add (info);
  381. }
  382. }
  383. detector.handleDevicesUpdated (devicesToUpdate);
  384. }
  385. Block::UID determineMasterBlockUid (Array<BlocksProtocol::DeviceStatus> devices)
  386. {
  387. if (masterSerialReader != nullptr && masterSerialReader->hasSerial())
  388. {
  389. auto foundSerial = masterSerialReader->getSerial();
  390. for (const auto& device : incomingTopologyDevices)
  391. {
  392. if (device.serialNumber.asString() == foundSerial)
  393. {
  394. LOG_CONNECTIVITY ("Found master from serial " + foundSerial);
  395. return getBlockUIDFromSerialNumber (foundSerial);
  396. }
  397. }
  398. }
  399. if (devices.size() > 0)
  400. {
  401. LOG_CONNECTIVITY ("Found master from first device " + devices[0].serialNumber.asString());
  402. return getBlockUIDFromSerialNumber (incomingTopologyDevices[0].serialNumber);
  403. }
  404. jassertfalse;
  405. return invalidUid;
  406. }
  407. //==============================================================================
  408. struct BlockPingTime
  409. {
  410. Block::UID blockUID;
  411. Time lastPing;
  412. Time connected;
  413. };
  414. Array<BlockPingTime> blockPings;
  415. BlockPingTime* getPing (Block::UID uid)
  416. {
  417. for (auto& ping : blockPings)
  418. if (uid == ping.blockUID)
  419. return &ping;
  420. return nullptr;
  421. }
  422. void removePing (Block::UID uid)
  423. {
  424. const auto remove = [uid] (const BlockPingTime& ping)
  425. {
  426. if (uid == ping.blockUID)
  427. {
  428. LOG_CONNECTIVITY ("API Disconnected by topology update " << ping.blockUID);
  429. return true;
  430. }
  431. return false;
  432. };
  433. blockPings.removeIf (remove);
  434. }
  435. void updateApiPing (Block::UID uid)
  436. {
  437. const auto now = Time::getCurrentTime();
  438. if (auto* ping = getPing (uid))
  439. {
  440. LOG_PING ("Ping: " << uid << " " << now.formatted ("%Mm %Ss"));
  441. ping->lastPing = now;
  442. }
  443. else
  444. {
  445. LOG_CONNECTIVITY ("API Connected " << uid);
  446. blockPings.add ({ uid, now, now });
  447. if (const auto info = getDeviceInfoFromUID (uid))
  448. detector.handleDeviceAdded (*info);
  449. }
  450. }
  451. bool isApiConnected (Block::UID uid)
  452. {
  453. return getPing (uid) != nullptr;
  454. }
  455. void forceApiDisconnected (Block::UID uid)
  456. {
  457. for (auto dependentUID : detector.getDnaDependentDeviceUIDs (uid))
  458. removeDevice (dependentUID);
  459. removeDevice (uid);
  460. if (uid == masterBlockUid)
  461. {
  462. masterBlockUid = invalidUid;
  463. masterSerialReader.reset();
  464. }
  465. scheduleNewTopologyRequest();
  466. }
  467. void checkApiTimeouts (Time now)
  468. {
  469. Array<Block::UID> toRemove;
  470. for (const auto& ping : blockPings)
  471. {
  472. if (ping.lastPing < now - RelativeTime::seconds (pingTimeoutSeconds))
  473. {
  474. LOG_CONNECTIVITY ("Ping timeout: " << ping.blockUID);
  475. toRemove.add (ping.blockUID);
  476. scheduleNewTopologyRequest();
  477. }
  478. }
  479. for (const auto& uid : toRemove)
  480. removeDevice (uid);
  481. }
  482. void startApiModeOnConnectedBlocks()
  483. {
  484. for (auto& info : currentDeviceInfo)
  485. {
  486. if (! isApiConnected (info.uid))
  487. {
  488. LOG_CONNECTIVITY ("API Try " << info.uid);
  489. sendCommandMessage (info.index, BlocksProtocol::endAPIMode);
  490. sendCommandMessage (info.index, BlocksProtocol::beginAPIMode);
  491. }
  492. }
  493. }
  494. //==============================================================================
  495. Block::UID getDeviceIDFromIndex (BlocksProtocol::TopologyIndex index) noexcept
  496. {
  497. for (const auto& device : currentDeviceInfo)
  498. if (device.index == index)
  499. return device.uid;
  500. scheduleNewTopologyRequest();
  501. return {};
  502. }
  503. int getIndexFromDeviceID (Block::UID uid) const noexcept
  504. {
  505. for (auto& d : currentDeviceInfo)
  506. if (d.uid == uid)
  507. return d.index;
  508. return -1;
  509. }
  510. DeviceInfo* getDeviceInfoFromUID (Block::UID uid) noexcept
  511. {
  512. for (auto& d : currentDeviceInfo)
  513. if (d.uid == uid)
  514. return &d;
  515. return nullptr;
  516. }
  517. DeviceInfo* getDeviceInfoFromIndex (BlocksProtocol::TopologyIndex index) noexcept
  518. {
  519. for (auto& d : currentDeviceInfo)
  520. if (d.index == index)
  521. return &d;
  522. return nullptr;
  523. }
  524. void removeDeviceInfo (Block::UID uid)
  525. {
  526. currentDeviceInfo.removeIf ([uid] (const DeviceInfo& info) { return info.uid == uid; });
  527. }
  528. const DeviceStatus* getIncomingDeviceStatus (BlockSerialNumber serialNumber) const
  529. {
  530. for (auto& device : incomingTopologyDevices)
  531. if (device.serialNumber == serialNumber)
  532. return &device;
  533. return nullptr;
  534. }
  535. //==============================================================================
  536. void removeDevice (Block::UID uid)
  537. {
  538. LOG_CONNECTIVITY ("Removing device: " << uid);
  539. if (const auto info = getDeviceInfoFromUID (uid))
  540. detector.handleDeviceRemoved (*info);
  541. removeDeviceInfo (uid);
  542. removePing (uid);
  543. }
  544. void updateCurrentDeviceList()
  545. {
  546. Array<Block::UID> toRemove;
  547. //Update known devices
  548. for (int i = currentDeviceInfo.size(); --i >= 0; )
  549. {
  550. auto& currentDevice = currentDeviceInfo.getReference (i);
  551. if (const auto newStatus = getIncomingDeviceStatus (currentDevice.serial))
  552. {
  553. if (currentDevice.index != newStatus->index)
  554. {
  555. currentDevice.index = newStatus->index;
  556. detector.handleIndexChanged (currentDevice.uid, currentDevice.index);
  557. }
  558. if (currentDevice.batteryCharging != newStatus->batteryCharging)
  559. {
  560. currentDevice.batteryCharging = newStatus->batteryCharging;
  561. detector.handleBatteryChargingChanged (currentDevice.uid, currentDevice.batteryCharging);
  562. }
  563. if (currentDevice.batteryLevel != newStatus->batteryLevel)
  564. {
  565. currentDevice.batteryLevel = newStatus->batteryLevel;
  566. detector.handleBatteryLevelChanged (currentDevice.uid, currentDevice.batteryLevel);
  567. }
  568. }
  569. else
  570. {
  571. toRemove.add (currentDevice.uid);
  572. }
  573. }
  574. for (const auto& uid : toRemove)
  575. removeDevice (uid);
  576. if (masterBlockUid == invalidUid)
  577. {
  578. masterBlockUid = determineMasterBlockUid (incomingTopologyDevices);
  579. initialiseVersionReader();
  580. }
  581. //Add new devices
  582. for (const auto& device : incomingTopologyDevices)
  583. {
  584. const auto uid = getBlockUIDFromSerialNumber (device.serialNumber);
  585. if (getDeviceInfoFromUID (uid) == nullptr)
  586. {
  587. currentDeviceInfo.add ({ uid,
  588. device.index,
  589. device.serialNumber,
  590. BlocksProtocol::VersionNumber(),
  591. BlocksProtocol::BlockName(),
  592. device.batteryLevel,
  593. device.batteryCharging,
  594. masterBlockUid });
  595. }
  596. }
  597. }
  598. //==============================================================================
  599. Block::ConnectionPort convertConnectionPort (Block::UID uid, BlocksProtocol::ConnectorPort p) noexcept
  600. {
  601. if (auto* info = getDeviceInfoFromUID (uid))
  602. return BlocksProtocol::BlockDataSheet (info->serial).convertPortIndexToConnectorPort (p);
  603. jassertfalse;
  604. return { Block::ConnectionPort::DeviceEdge::north, 0 };
  605. }
  606. BlockDeviceConnection getBlockDeviceConnection (const BlocksProtocol::DeviceConnection& connection)
  607. {
  608. BlockDeviceConnection dc;
  609. dc.device1 = getDeviceIDFromIndex (connection.device1);
  610. dc.device2 = getDeviceIDFromIndex (connection.device2);
  611. if (dc.device1 <= 0 || dc.device2 <= 0)
  612. jassertfalse;
  613. dc.connectionPortOnDevice1 = convertConnectionPort (dc.device1, connection.port1);
  614. dc.connectionPortOnDevice2 = convertConnectionPort (dc.device2, connection.port2);
  615. return dc;
  616. }
  617. void updateCurrentDeviceConnections()
  618. {
  619. currentDeviceConnections.clearQuick();
  620. currentDeviceConnections.swapWith (incomingTopologyConnections);
  621. detector.handleConnectionsChanged();
  622. }
  623. void initialiseVersionReader()
  624. {
  625. if (auto midiDeviceConnection = static_cast<MIDIDeviceConnection*> (deviceConnection.get()))
  626. depreciatedVersionReader = std::make_unique<DepreciatedVersionReader> (*midiDeviceConnection);
  627. }
  628. void initialiseSerialReader()
  629. {
  630. if (auto midiDeviceConnection = static_cast<MIDIDeviceConnection*> (deviceConnection.get()))
  631. masterSerialReader = std::make_unique<BlockSerialReader> (*midiDeviceConnection);
  632. }
  633. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectedDeviceGroup)
  634. };
  635. } // namespace juce