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.

126 lines
5.0KB

  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. Acting as a ResponderListener, instances of this class can formulate
  22. appropriate replies to property transactions initiated by remote devices.
  23. PropertyHost instances also contain methods to inform remote devices about
  24. changes to local property state.
  25. Keeps track of property subscriptions requested by remote devices.
  26. @tags{Audio}
  27. */
  28. class PropertyHost final : public ResponderDelegate
  29. {
  30. public:
  31. /** @internal
  32. Rather than constructing one of these objects yourself, you should configure
  33. a Device with property exchange support, and then use Device::getPropertyHost()
  34. to retrieve a property host that has been set up to work with that device.
  35. */
  36. PropertyHost (FunctionBlock fb, PropertyDelegate& d, BufferOutput& o, CacheProvider& p)
  37. : functionBlock (fb), delegate (d), output (o), cacheProvider (p) {}
  38. /** Sends a "Subscription" message from a device, when acting as a
  39. subscription responder. You should call this for all registered
  40. subscribers whenever the subscribed property is modified in a way that
  41. remote devices don't know about (if a remote device requests a
  42. property update, there's no need to send a subscription update after
  43. changing the property accordingly).
  44. You should *not* attempt to start a new subscription on another device
  45. using this function. Valid subscription commands are "full", "partial",
  46. and "notify". Check the property exchange specification for the intended
  47. use of these commands.
  48. To terminate a subscription that was initiated by a remote device,
  49. use terminateSubscription().
  50. The provided callback will be called once the remote device has confirmed
  51. receipt of the subscription update. If the state of your application
  52. changes such that you no longer need to respond/wait for confirmation,
  53. you can allow the returned Guard to fall out of scope, or reset it
  54. manually.
  55. */
  56. ErasedScopeGuard sendSubscriptionUpdate (MUID device,
  57. const PropertySubscriptionHeader& header,
  58. Span<const std::byte> body,
  59. std::function<void (const PropertyExchangeResult&)> callback);
  60. /** Terminates a subscription that was started by a remote device.
  61. This may be useful if your application has properties that can be
  62. added and removed - you can terminate subscriptions to subscribed
  63. properties before removing those properties.
  64. */
  65. void terminateSubscription (MUID device, const String& subscribeId);
  66. /** Returns a set of subscribed resources.
  67. This set contains all active subscriptionIDs for the given device,
  68. along with the resources to which those subscriptionIDs refer.
  69. */
  70. std::set<Subscription> findSubscriptionsForDevice (MUID device) const;
  71. /** Returns the number of transactions that have been initiated by other devices, but not yet
  72. completed, normally because the request has been split into several messages.
  73. */
  74. int countOngoingTransactions() const;
  75. /** @internal */
  76. bool tryRespond (ResponderOutput&, const Message::Parsed&) override;
  77. private:
  78. class Visitor;
  79. struct SubscriptionToken
  80. {
  81. size_t uid{};
  82. bool operator< (const SubscriptionToken& other) const { return uid < other.uid; }
  83. bool operator== (const SubscriptionToken& other) const { return uid == other.uid; }
  84. bool operator!= (const SubscriptionToken& other) const { return uid != other.uid; }
  85. };
  86. static SubscriptionToken uidFromSubscribeId (String id);
  87. static String subscribeIdFromUid (SubscriptionToken uid);
  88. static SubscriptionToken findUnusedSubscribeId (const std::map<SubscriptionToken, String>& used);
  89. FunctionBlock functionBlock;
  90. PropertyDelegate& delegate;
  91. BufferOutput& output;
  92. CacheProvider& cacheProvider;
  93. std::map<MUID, std::map<SubscriptionToken, String>> registry;
  94. };
  95. } // namespace juce::midi_ci