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.

280 lines
8.1KB

  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. #define JUCE_SUBSCRIPTION_COMMANDS X(start) X(partial) X(full) X(notify) X(end)
  21. /**
  22. Kinds of command that may be sent as part of a subscription update.
  23. Check the Property Exchange specification to find the meaning of the
  24. different kinds.
  25. @tags{Audio}
  26. */
  27. enum class PropertySubscriptionCommand
  28. {
  29. #define X(str) str,
  30. JUCE_SUBSCRIPTION_COMMANDS
  31. #undef X
  32. };
  33. /**
  34. Functions to use with PropertySubscriptionCommand.
  35. @tags{Audio}
  36. */
  37. struct PropertySubscriptionCommandUtils
  38. {
  39. PropertySubscriptionCommandUtils() = delete;
  40. /** Converts a command to a human-readable string. */
  41. static const char* toString (PropertySubscriptionCommand x)
  42. {
  43. switch (x)
  44. {
  45. #define X(str) case PropertySubscriptionCommand::str: return #str;
  46. JUCE_SUBSCRIPTION_COMMANDS
  47. #undef X
  48. }
  49. return nullptr;
  50. }
  51. /** Converts a command string from a property exchange JSON header to
  52. an PropertySubscriptionCommand.
  53. */
  54. static std::optional<PropertySubscriptionCommand> toCommand (const char* str)
  55. {
  56. #define X(name) if (std::string_view (str) == std::string_view (#name)) return PropertySubscriptionCommand::name;
  57. JUCE_SUBSCRIPTION_COMMANDS
  58. #undef X
  59. return {};
  60. }
  61. };
  62. #undef JUCE_SUBSCRIPTION_COMMANDS
  63. /**
  64. A struct containing data members that correspond to common fields in a
  65. property subscription header.
  66. Check the Property Exchange specification to find the meaning of the
  67. different fields.
  68. @tags{Audio}
  69. */
  70. struct PropertySubscriptionHeader
  71. {
  72. String resource;
  73. String resId;
  74. Encoding mutualEncoding = Encoding::ascii;
  75. String mediaType = "application/json";
  76. PropertySubscriptionCommand command { -1 };
  77. String subscribeId;
  78. std::map<Identifier, var> extended;
  79. /** Converts a JSON object to a PropertyRequestHeader.
  80. Unspecified fields will use their default values.
  81. */
  82. static PropertySubscriptionHeader parseCondensed (const var&);
  83. /** Converts a PropertySubscriptionHeader to a JSON object suitable for use as
  84. a MIDI-CI message header after conversion to 7-bit ASCII.
  85. */
  86. var toVarCondensed() const;
  87. };
  88. /**
  89. Contains information about the pagination of a request.
  90. Check the Property Exchange specification to find the meaning of the
  91. different fields.
  92. @tags{Audio}
  93. */
  94. struct Pagination
  95. {
  96. int offset = 0;
  97. int limit = 1;
  98. };
  99. /**
  100. A struct containing data members that correspond to common fields in a
  101. property request header.
  102. Check the Property Exchange specification to find the meaning of the
  103. different fields.
  104. @tags{Audio}
  105. */
  106. struct PropertyRequestHeader
  107. {
  108. String resource;
  109. String resId;
  110. Encoding mutualEncoding = Encoding::ascii;
  111. String mediaType = "application/json";
  112. bool setPartial = false;
  113. std::optional<Pagination> pagination;
  114. std::map<Identifier, var> extended;
  115. /** Converts a JSON object to a PropertyRequestHeader.
  116. Unspecified fields will use their default values.
  117. */
  118. static PropertyRequestHeader parseCondensed (const var&);
  119. /** Converts a PropertyRequestHeader to a JSON object suitable for use as
  120. a MIDI-CI message header after conversion to 7-bit ASCII.
  121. */
  122. var toVarCondensed() const;
  123. };
  124. /**
  125. Bundles together a property request header and a data payload.
  126. @tags{Audio}
  127. */
  128. struct PropertyRequestData
  129. {
  130. PropertyRequestHeader header;
  131. Span<const std::byte> body;
  132. };
  133. /**
  134. A struct containing data members that correspond to common fields in a
  135. reply to a property exchange request.
  136. Check the Property Exchange specification to find the meaning of the
  137. different fields.
  138. For extended attributes that don't correspond to any of the defined data
  139. members, use the 'extended' map.
  140. @tags{Audio}
  141. */
  142. struct PropertyReplyHeader
  143. {
  144. int status = 200;
  145. String message;
  146. Encoding mutualEncoding = Encoding::ascii;
  147. int cacheTime = 0;
  148. String mediaType = "application/json";
  149. std::map<Identifier, var> extended;
  150. /** Converts a JSON object to a PropertyReplyHeader.
  151. Unspecified fields will use their default values.
  152. */
  153. static PropertyReplyHeader parseCondensed (const var&);
  154. /** Converts a PropertyReplyHeader to a JSON object suitable for use as
  155. a MIDI-CI message header after conversion to 7-bit ASCII.
  156. */
  157. var toVarCondensed() const;
  158. };
  159. /**
  160. Bundles together a property reply header and a data payload.
  161. @tags{Audio}
  162. */
  163. struct PropertyReplyData
  164. {
  165. PropertyReplyHeader header;
  166. std::vector<std::byte> body;
  167. };
  168. /**
  169. An interface with methods that can be overridden to customise how a Device
  170. implementing properties responds to property inquiries.
  171. @tags{Audio}
  172. */
  173. struct PropertyDelegate
  174. {
  175. PropertyDelegate() = default;
  176. virtual ~PropertyDelegate() = default;
  177. PropertyDelegate (const PropertyDelegate&) = default;
  178. PropertyDelegate (PropertyDelegate&&) = default;
  179. PropertyDelegate& operator= (const PropertyDelegate&) = default;
  180. PropertyDelegate& operator= (PropertyDelegate&&) = default;
  181. /** Returns the max number of simultaneous property exchange messages that can be processed. */
  182. virtual uint8_t getNumSimultaneousRequestsSupported() const { return 127; }
  183. /** Returns a header/body containing the requested data.
  184. To report an error, you can return a failure status code in the header and leave the body empty.
  185. */
  186. virtual PropertyReplyData propertyGetDataRequested (MUID, const PropertyRequestHeader&) = 0;
  187. /** Returns a header that describes the result of the set operation. */
  188. virtual PropertyReplyHeader propertySetDataRequested (MUID, const PropertyRequestData&) = 0;
  189. /** Returns true to allow the subscription, or false otherwise. */
  190. virtual bool subscriptionStartRequested (MUID, const PropertySubscriptionHeader&) = 0;
  191. /** Called with the corresponding subscription token after a subscription has started. */
  192. virtual void subscriptionDidStart (MUID, const String& subId, const PropertySubscriptionHeader&) = 0;
  193. /** Called when a device requests for an ongoing subscription to end. */
  194. virtual void subscriptionWillEnd (MUID, const Subscription& sub) = 0;
  195. };
  196. } // namespace juce::midi_ci
  197. #ifndef DOXYGEN
  198. namespace juce
  199. {
  200. template <>
  201. struct SerialisationTraits<midi_ci::PropertySubscriptionCommand>
  202. {
  203. static constexpr auto marshallingVersion = std::nullopt;
  204. template <typename Archive>
  205. void load (Archive& archive, midi_ci::PropertySubscriptionCommand& t)
  206. {
  207. String command;
  208. archive (command);
  209. t = midi_ci::PropertySubscriptionCommandUtils::toCommand (command.toRawUTF8()).value_or (midi_ci::PropertySubscriptionCommand{});
  210. }
  211. template <typename Archive>
  212. void save (Archive& archive, const midi_ci::PropertySubscriptionCommand& t)
  213. {
  214. archive (midi_ci::PropertySubscriptionCommandUtils::toString (t));
  215. }
  216. };
  217. } // namespace juce
  218. #endif // ifndef DOXYGEN