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.

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