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.

251 lines
7.2KB

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