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.

161 lines
5.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce::midi_ci
  19. {
  20. /**
  21. Accumulates message chunks that have been sent by another device in response
  22. to a transaction initiated by a local device.
  23. @tags{Audio}
  24. */
  25. class InitiatorPropertyExchangeCache
  26. {
  27. public:
  28. InitiatorPropertyExchangeCache();
  29. ~InitiatorPropertyExchangeCache();
  30. InitiatorPropertyExchangeCache (InitiatorPropertyExchangeCache&&) noexcept;
  31. InitiatorPropertyExchangeCache& operator= (InitiatorPropertyExchangeCache&&) noexcept;
  32. JUCE_DECLARE_NON_COPYABLE (InitiatorPropertyExchangeCache)
  33. /** Holds a token that can be used to stop waiting for a reply, along with
  34. an identifier byte that uniquely identifies an ongoing transaction.
  35. @tags{Audio}
  36. */
  37. struct TokenAndId
  38. {
  39. TokenAndId() = default;
  40. TokenAndId (ErasedScopeGuard tokenIn, std::byte idIn)
  41. : token (std::move (tokenIn)), id (idIn) {}
  42. bool isValid() const { return (id & std::byte { 0x80 }) == std::byte{}; }
  43. ErasedScopeGuard token{};
  44. std::byte id { 0x80 };
  45. };
  46. /** Picks an unused request ID, and prepares the cache for that ID to accumulate message chunks.
  47. Incoming chunks added with addChunk are generated by another device acting as a responder.
  48. */
  49. TokenAndId primeCache (uint8_t maxSimultaneousRequests,
  50. std::function<void (const PropertyExchangeResult&)> onDone,
  51. std::function<void (std::byte)> onTerminate);
  52. /** Adds a message chunk for the provided transaction id. */
  53. void addChunk (std::byte b, const Message::DynamicSizePropertyExchange& chunk);
  54. /** Updates the transaction state based on the contents of the provided notification. */
  55. void notify (std::byte b, Span<const std::byte> header);
  56. /** Returns the number of transactions that have been started but not finished. */
  57. int countOngoingTransactions() const;
  58. /** Returns true if there are any transactions in progress that
  59. haven't yet received replies.
  60. */
  61. bool isAwaitingResponse() const;
  62. private:
  63. class Impl;
  64. std::unique_ptr<Impl> pimpl;
  65. };
  66. //==============================================================================
  67. /**
  68. Accumulates message chunks that form a request initiated by a remote device.
  69. @tags{Audio}
  70. */
  71. class ResponderPropertyExchangeCache
  72. {
  73. public:
  74. ResponderPropertyExchangeCache();
  75. ~ResponderPropertyExchangeCache();
  76. ResponderPropertyExchangeCache (ResponderPropertyExchangeCache&&) noexcept;
  77. ResponderPropertyExchangeCache& operator= (ResponderPropertyExchangeCache&&) noexcept;
  78. JUCE_DECLARE_NON_COPYABLE (ResponderPropertyExchangeCache)
  79. /** Prepares the cache for the given requestId to accumulate message chunks.
  80. Incoming chunks added with addChunk are generated by another device acting as an initiator.
  81. */
  82. void primeCache (uint8_t maxSimultaneousTransactions,
  83. std::function<void (const PropertyExchangeResult&)> onDone,
  84. std::byte id);
  85. /** Adds a message chunk for the provided transaction id. */
  86. void addChunk (std::byte b, const Message::DynamicSizePropertyExchange& chunk);
  87. /** Updates the transaction state based on the contents of the provided notification. */
  88. void notify (std::byte b, Span<const std::byte> header);
  89. /** Returns the number of transactions that have been started but not finished. */
  90. int countOngoingTransactions() const;
  91. private:
  92. class Impl;
  93. std::unique_ptr<Impl> pimpl;
  94. };
  95. //==============================================================================
  96. /**
  97. An interface for objects that provide resources for property exchange
  98. transactions.
  99. @tags{Audio}
  100. */
  101. class CacheProvider
  102. {
  103. public:
  104. virtual ~CacheProvider() = default;
  105. /** Returns a set containing all of the MUIDs currently known to the provider. */
  106. virtual std::set<MUID> getDiscoveredMuids() const = 0;
  107. /** Returns a property exchange cache for accumulating replies to transactions
  108. we initiated.
  109. */
  110. virtual InitiatorPropertyExchangeCache* getCacheForMuidAsInitiator (MUID m) = 0;
  111. /** Returns a property exchange cache for accumulating requests initiated
  112. by other devices.
  113. */
  114. virtual ResponderPropertyExchangeCache* getCacheForMuidAsResponder (MUID m) = 0;
  115. /** Returns the maximum sysex size supported by the device with the
  116. given MUID.
  117. */
  118. virtual int getMaxSysexSizeForMuid (MUID m) const = 0;
  119. };
  120. } // namespace juce::midi_ci