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.

247 lines
7.1KB

  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() : UnitTest ("OSCBundle class", "OSC") {}
  95. void runTest()
  96. {
  97. beginTest ("Construction");
  98. {
  99. OSCBundle bundle;
  100. expect (bundle.getTimeTag().isImmediately());
  101. }
  102. beginTest ("Construction with time tag");
  103. {
  104. Time in100Seconds = (Time (Time::currentTimeMillis()) + RelativeTime (100.0));
  105. OSCBundle bundle (in100Seconds);
  106. expect (! bundle.getTimeTag().isImmediately());
  107. expect (bundle.getTimeTag().toTime() == in100Seconds);
  108. }
  109. beginTest ("Usage when containing messages");
  110. {
  111. OSCBundle testBundle = generateTestBundle();
  112. expectBundleEqualsTestBundle (testBundle);
  113. }
  114. beginTest ("Usage when containing other bundles (recursively)");
  115. {
  116. OSCBundle complexTestBundle;
  117. complexTestBundle.addElement (generateTestBundle());
  118. complexTestBundle.addElement (OSCMessage ("/test/"));
  119. complexTestBundle.addElement (generateTestBundle());
  120. expect (complexTestBundle.size() == 3);
  121. OSCBundle::Element* elements = complexTestBundle.begin();
  122. expect (! elements[0].isMessage());
  123. expect (elements[0].isBundle());
  124. expect (elements[1].isMessage());
  125. expect (! elements[1].isBundle());
  126. expect (! elements[2].isMessage());
  127. expect (elements[2].isBundle());
  128. expectBundleEqualsTestBundle (elements[0].getBundle());
  129. expect (elements[1].getMessage().size() == 0);
  130. expect (elements[1].getMessage().getAddressPattern().toString() == "/test");
  131. expectBundleEqualsTestBundle (elements[2].getBundle());
  132. }
  133. }
  134. private:
  135. int testInt = 127;
  136. float testFloat = 1.5;
  137. OSCBundle generateTestBundle()
  138. {
  139. OSCBundle bundle;
  140. OSCMessage msg1 ("/test/fader");
  141. msg1.addInt32 (testInt);
  142. OSCMessage msg2 ("/test/foo");
  143. msg2.addString ("bar");
  144. msg2.addFloat32 (testFloat);
  145. bundle.addElement (msg1);
  146. bundle.addElement (msg2);
  147. return bundle;
  148. }
  149. void expectBundleEqualsTestBundle (const OSCBundle& bundle)
  150. {
  151. expect (bundle.size() == 2);
  152. expect (bundle[0].isMessage());
  153. expect (! bundle[0].isBundle());
  154. expect (bundle[1].isMessage());
  155. expect (! bundle[1].isBundle());
  156. int numElementsCounted = 0;
  157. for (auto& element : bundle)
  158. {
  159. expect (element.isMessage());
  160. expect (! element.isBundle());
  161. ++numElementsCounted;
  162. }
  163. expectEquals (numElementsCounted, 2);
  164. auto* e = bundle.begin();
  165. expect (e[0].getMessage().size() == 1);
  166. expect (e[0].getMessage().begin()->getInt32() == testInt);
  167. expect (e[1].getMessage().size() == 2);
  168. expect (e[1].getMessage()[1].getFloat32() == testFloat);
  169. }
  170. };
  171. static OSCBundleTests OSCBundleUnitTests;
  172. //==============================================================================
  173. class OSCBundleElementTests : public UnitTest
  174. {
  175. public:
  176. OSCBundleElementTests() : UnitTest ("OSCBundle::Element class", "OSC") {}
  177. void runTest()
  178. {
  179. beginTest ("Construction from OSCMessage");
  180. {
  181. float testFloat = -0.125;
  182. OSCMessage msg ("/test");
  183. msg.addFloat32 (testFloat);
  184. OSCBundle::Element element (msg);
  185. expect (element.isMessage());
  186. expect (element.getMessage().size() == 1);
  187. expect (element.getMessage()[0].getType() == OSCTypes::float32);
  188. expect (element.getMessage()[0].getFloat32() == testFloat);
  189. }
  190. }
  191. };
  192. static OSCBundleElementTests OSCBundleElementUnitTests;
  193. #endif
  194. } // namespace juce