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.

291 lines
6.7KB

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