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.

250 lines
7.2KB

  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. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-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
  19. {
  20. OSCBundle::OSCBundle()
  21. {
  22. }
  23. OSCBundle::OSCBundle (OSCTimeTag t) : timeTag (t)
  24. {
  25. }
  26. // Note: The class invariant of OSCBundle::Element is that
  27. // at least one of the pointers bundle and message is nullptr
  28. // and the other one always points to a valid object.
  29. OSCBundle::Element::Element (OSCMessage m)
  30. : message (new OSCMessage (m)), bundle (nullptr)
  31. {
  32. }
  33. OSCBundle::Element::Element (OSCBundle b)
  34. : message (nullptr), bundle (new OSCBundle (b))
  35. {
  36. }
  37. //==============================================================================
  38. OSCBundle::Element::Element (const Element& other)
  39. {
  40. if (this != &other)
  41. {
  42. message = nullptr;
  43. bundle = nullptr;
  44. if (other.isMessage())
  45. message.reset (new OSCMessage (other.getMessage()));
  46. else
  47. bundle.reset (new OSCBundle (other.getBundle()));
  48. }
  49. }
  50. //==============================================================================
  51. OSCBundle::Element::~Element()
  52. {
  53. bundle = nullptr;
  54. message = nullptr;
  55. }
  56. //==============================================================================
  57. bool OSCBundle::Element::isMessage() const noexcept
  58. {
  59. return message != nullptr;
  60. }
  61. bool OSCBundle::Element::isBundle() const noexcept
  62. {
  63. return bundle != nullptr;
  64. }
  65. //==============================================================================
  66. const OSCMessage& OSCBundle::Element::getMessage() const
  67. {
  68. if (message == nullptr)
  69. {
  70. // This element is not a bundle! You must check this first before accessing.
  71. jassertfalse;
  72. throw OSCInternalError ("Access error in OSC bundle element.");
  73. }
  74. return *message;
  75. }
  76. //==============================================================================
  77. const OSCBundle& OSCBundle::Element::getBundle() const
  78. {
  79. if (bundle == nullptr)
  80. {
  81. // This element is not a bundle! You must check this first before accessing.
  82. jassertfalse;
  83. throw OSCInternalError ("Access error in OSC bundle element.");
  84. }
  85. return *bundle;
  86. }
  87. //==============================================================================
  88. //==============================================================================
  89. #if JUCE_UNIT_TESTS
  90. class OSCBundleTests : public UnitTest
  91. {
  92. public:
  93. OSCBundleTests()
  94. : UnitTest ("OSCBundle class", UnitTestCategories::osc)
  95. {}
  96. void runTest()
  97. {
  98. beginTest ("Construction");
  99. {
  100. OSCBundle bundle;
  101. expect (bundle.getTimeTag().isImmediately());
  102. }
  103. beginTest ("Construction with time tag");
  104. {
  105. Time in100Seconds = (Time (Time::currentTimeMillis()) + RelativeTime (100.0));
  106. OSCBundle bundle (in100Seconds);
  107. expect (! bundle.getTimeTag().isImmediately());
  108. expect (bundle.getTimeTag().toTime() == in100Seconds);
  109. }
  110. beginTest ("Usage when containing messages");
  111. {
  112. OSCBundle testBundle = generateTestBundle();
  113. expectBundleEqualsTestBundle (testBundle);
  114. }
  115. beginTest ("Usage when containing other bundles (recursively)");
  116. {
  117. OSCBundle complexTestBundle;
  118. complexTestBundle.addElement (generateTestBundle());
  119. complexTestBundle.addElement (OSCMessage ("/test/"));
  120. complexTestBundle.addElement (generateTestBundle());
  121. expect (complexTestBundle.size() == 3);
  122. OSCBundle::Element* elements = complexTestBundle.begin();
  123. expect (! elements[0].isMessage());
  124. expect (elements[0].isBundle());
  125. expect (elements[1].isMessage());
  126. expect (! elements[1].isBundle());
  127. expect (! elements[2].isMessage());
  128. expect (elements[2].isBundle());
  129. expectBundleEqualsTestBundle (elements[0].getBundle());
  130. expect (elements[1].getMessage().size() == 0);
  131. expect (elements[1].getMessage().getAddressPattern().toString() == "/test");
  132. expectBundleEqualsTestBundle (elements[2].getBundle());
  133. }
  134. }
  135. private:
  136. int testInt = 127;
  137. float testFloat = 1.5;
  138. OSCBundle generateTestBundle()
  139. {
  140. OSCBundle bundle;
  141. OSCMessage msg1 ("/test/fader");
  142. msg1.addInt32 (testInt);
  143. OSCMessage msg2 ("/test/foo");
  144. msg2.addString ("bar");
  145. msg2.addFloat32 (testFloat);
  146. bundle.addElement (msg1);
  147. bundle.addElement (msg2);
  148. return bundle;
  149. }
  150. void expectBundleEqualsTestBundle (const OSCBundle& bundle)
  151. {
  152. expect (bundle.size() == 2);
  153. expect (bundle[0].isMessage());
  154. expect (! bundle[0].isBundle());
  155. expect (bundle[1].isMessage());
  156. expect (! bundle[1].isBundle());
  157. int numElementsCounted = 0;
  158. for (auto& element : bundle)
  159. {
  160. expect (element.isMessage());
  161. expect (! element.isBundle());
  162. ++numElementsCounted;
  163. }
  164. expectEquals (numElementsCounted, 2);
  165. auto* e = bundle.begin();
  166. expect (e[0].getMessage().size() == 1);
  167. expect (e[0].getMessage().begin()->getInt32() == testInt);
  168. expect (e[1].getMessage().size() == 2);
  169. expect (e[1].getMessage()[1].getFloat32() == testFloat);
  170. }
  171. };
  172. static OSCBundleTests OSCBundleUnitTests;
  173. //==============================================================================
  174. class OSCBundleElementTests : public UnitTest
  175. {
  176. public:
  177. OSCBundleElementTests()
  178. : UnitTest ("OSCBundle::Element class", UnitTestCategories::osc)
  179. {}
  180. void runTest()
  181. {
  182. beginTest ("Construction from OSCMessage");
  183. {
  184. float testFloat = -0.125;
  185. OSCMessage msg ("/test");
  186. msg.addFloat32 (testFloat);
  187. OSCBundle::Element element (msg);
  188. expect (element.isMessage());
  189. expect (element.getMessage().size() == 1);
  190. expect (element.getMessage()[0].getType() == OSCTypes::float32);
  191. expect (element.getMessage()[0].getFloat32() == testFloat);
  192. }
  193. }
  194. };
  195. static OSCBundleElementTests OSCBundleElementUnitTests;
  196. #endif
  197. } // namespace juce