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.

306 lines
7.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. class SharedValueSourceUpdater : public ReferenceCountedObject,
  19. private AsyncUpdater
  20. {
  21. public:
  22. SharedValueSourceUpdater() : sourcesBeingIterated (nullptr) {}
  23. ~SharedValueSourceUpdater() { masterReference.clear(); }
  24. void update (Value::ValueSource* const source)
  25. {
  26. sourcesNeedingAnUpdate.add (source);
  27. if (sourcesBeingIterated == nullptr)
  28. triggerAsyncUpdate();
  29. }
  30. void valueDeleted (Value::ValueSource* const source)
  31. {
  32. sourcesNeedingAnUpdate.removeValue (source);
  33. if (sourcesBeingIterated != nullptr)
  34. sourcesBeingIterated->removeValue (source);
  35. }
  36. WeakReference<SharedValueSourceUpdater>::Master masterReference;
  37. private:
  38. typedef SortedSet<Value::ValueSource*> SourceSet;
  39. SourceSet sourcesNeedingAnUpdate;
  40. SourceSet* sourcesBeingIterated;
  41. void handleAsyncUpdate()
  42. {
  43. const ReferenceCountedObjectPtr<SharedValueSourceUpdater> localRef (this);
  44. {
  45. const ScopedValueSetter<SourceSet*> inside (sourcesBeingIterated, nullptr, nullptr);
  46. int maxLoops = 10;
  47. while (sourcesNeedingAnUpdate.size() > 0)
  48. {
  49. if (--maxLoops == 0)
  50. {
  51. triggerAsyncUpdate();
  52. break;
  53. }
  54. SourceSet sources;
  55. sources.swapWith (sourcesNeedingAnUpdate);
  56. sourcesBeingIterated = &sources;
  57. for (int i = sources.size(); --i >= 0;)
  58. if (i < sources.size())
  59. sources.getUnchecked(i)->sendChangeMessage (true);
  60. }
  61. }
  62. }
  63. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedValueSourceUpdater)
  64. };
  65. static WeakReference<SharedValueSourceUpdater> sharedUpdater;
  66. Value::ValueSource::ValueSource()
  67. {
  68. }
  69. Value::ValueSource::~ValueSource()
  70. {
  71. if (asyncUpdater != nullptr)
  72. static_cast <SharedValueSourceUpdater*> (asyncUpdater.get())->valueDeleted (this);
  73. }
  74. void Value::ValueSource::sendChangeMessage (const bool synchronous)
  75. {
  76. const int numListeners = valuesWithListeners.size();
  77. if (numListeners > 0)
  78. {
  79. if (synchronous)
  80. {
  81. const ReferenceCountedObjectPtr<ValueSource> localRef (this);
  82. asyncUpdater = nullptr;
  83. for (int i = numListeners; --i >= 0;)
  84. if (Value* const v = valuesWithListeners[i])
  85. v->callListeners();
  86. }
  87. else
  88. {
  89. SharedValueSourceUpdater* updater = static_cast <SharedValueSourceUpdater*> (asyncUpdater.get());
  90. if (updater == nullptr)
  91. {
  92. if (sharedUpdater == nullptr)
  93. {
  94. asyncUpdater = updater = new SharedValueSourceUpdater();
  95. sharedUpdater = updater;
  96. }
  97. else
  98. {
  99. asyncUpdater = updater = sharedUpdater.get();
  100. }
  101. }
  102. updater->update (this);
  103. }
  104. }
  105. }
  106. //==============================================================================
  107. class SimpleValueSource : public Value::ValueSource
  108. {
  109. public:
  110. SimpleValueSource()
  111. {
  112. }
  113. SimpleValueSource (const var& initialValue)
  114. : value (initialValue)
  115. {
  116. }
  117. var getValue() const
  118. {
  119. return value;
  120. }
  121. void setValue (const var& newValue)
  122. {
  123. if (! newValue.equalsWithSameType (value))
  124. {
  125. value = newValue;
  126. sendChangeMessage (false);
  127. }
  128. }
  129. private:
  130. var value;
  131. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleValueSource)
  132. };
  133. //==============================================================================
  134. Value::Value()
  135. : value (new SimpleValueSource())
  136. {
  137. }
  138. Value::Value (ValueSource* const v)
  139. : value (v)
  140. {
  141. jassert (v != nullptr);
  142. }
  143. Value::Value (const var& initialValue)
  144. : value (new SimpleValueSource (initialValue))
  145. {
  146. }
  147. Value::Value (const Value& other)
  148. : value (other.value)
  149. {
  150. }
  151. Value& Value::operator= (const Value& other)
  152. {
  153. value = other.value;
  154. return *this;
  155. }
  156. #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
  157. Value::Value (Value&& other) noexcept
  158. : value (static_cast <ReferenceCountedObjectPtr <ValueSource>&&> (other.value))
  159. {
  160. }
  161. Value& Value::operator= (Value&& other) noexcept
  162. {
  163. value = static_cast <ReferenceCountedObjectPtr <ValueSource>&&> (other.value);
  164. return *this;
  165. }
  166. #endif
  167. Value::~Value()
  168. {
  169. if (listeners.size() > 0)
  170. value->valuesWithListeners.removeValue (this);
  171. }
  172. //==============================================================================
  173. var Value::getValue() const
  174. {
  175. return value->getValue();
  176. }
  177. Value::operator var() const
  178. {
  179. return value->getValue();
  180. }
  181. void Value::setValue (const var& newValue)
  182. {
  183. value->setValue (newValue);
  184. }
  185. String Value::toString() const
  186. {
  187. return value->getValue().toString();
  188. }
  189. Value& Value::operator= (const var& newValue)
  190. {
  191. value->setValue (newValue);
  192. return *this;
  193. }
  194. void Value::referTo (const Value& valueToReferTo)
  195. {
  196. if (valueToReferTo.value != value)
  197. {
  198. if (listeners.size() > 0)
  199. {
  200. value->valuesWithListeners.removeValue (this);
  201. valueToReferTo.value->valuesWithListeners.add (this);
  202. }
  203. value = valueToReferTo.value;
  204. callListeners();
  205. }
  206. }
  207. bool Value::refersToSameSourceAs (const Value& other) const
  208. {
  209. return value == other.value;
  210. }
  211. bool Value::operator== (const Value& other) const
  212. {
  213. return value == other.value || value->getValue() == other.getValue();
  214. }
  215. bool Value::operator!= (const Value& other) const
  216. {
  217. return value != other.value && value->getValue() != other.getValue();
  218. }
  219. //==============================================================================
  220. void Value::addListener (ValueListener* const listener)
  221. {
  222. if (listener != nullptr)
  223. {
  224. if (listeners.size() == 0)
  225. value->valuesWithListeners.add (this);
  226. listeners.add (listener);
  227. }
  228. }
  229. void Value::removeListener (ValueListener* const listener)
  230. {
  231. listeners.remove (listener);
  232. if (listeners.size() == 0)
  233. value->valuesWithListeners.removeValue (this);
  234. }
  235. void Value::callListeners()
  236. {
  237. if (listeners.size() > 0)
  238. {
  239. Value v (*this); // (create a copy in case this gets deleted by a callback)
  240. listeners.call (&ValueListener::valueChanged, v);
  241. }
  242. }
  243. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Value& value)
  244. {
  245. return stream << value.toString();
  246. }