Audio plugin host https://kx.studio/carla
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.

252 lines
9.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. /** Used to implement 'attachments' or 'controllers' that link a plug-in
  21. parameter to a UI element.
  22. To implement a new attachment type, create a new class which includes an
  23. instance of this class as a data member. Your class should pass a function
  24. to the constructor of the ParameterAttachment, which will then be called on
  25. the message thread when the parameter changes. You can use this function to
  26. update the state of the UI control. Your class should also register as a
  27. listener of the UI control and respond to respond to changes in the UI element
  28. by calling either setValueAsCompleteGesture or beginGesture,
  29. setValueAsPartOfGesture and endGesture.
  30. Make sure to call `sendInitialUpdate` at the end of your new attachment's
  31. constructor, so that the UI immediately reflects the state of the parameter.
  32. @tags{Audio}
  33. */
  34. class ParameterAttachment : private AudioProcessorParameter::Listener,
  35. private AsyncUpdater
  36. {
  37. public:
  38. /** Listens to a parameter and calls the the provided function in response to
  39. parameter changes. If an undoManager is supplied `beginNewTransaction` will
  40. be called on it whenever the UI requests a parameter change via this attachment.
  41. @param parameter The parameter to which this attachment will listen
  42. @param parameterChangedCallback The function that will be called on the message thread in response
  43. to parameter changes
  44. @param undoManager The UndoManager that will be used to begin transactions when the UI
  45. requests a parameter change.
  46. */
  47. ParameterAttachment (RangedAudioParameter& parameter,
  48. std::function<void (float)> parameterChangedCallback,
  49. UndoManager* undoManager = nullptr);
  50. /** Destructor. */
  51. ~ParameterAttachment() override;
  52. /** Calls the parameterChangedCallback function that was registered in
  53. the constructor, making the UI reflect the current parameter state.
  54. This function should be called after doing any necessary setup on
  55. the UI control that is being managed (e.g. adding ComboBox entries,
  56. making buttons toggle-able).
  57. */
  58. void sendInitialUpdate();
  59. /** Triggers a full gesture message on the managed parameter.
  60. Call this in the listener callback of the UI control in response
  61. to a one-off change in the UI like a button-press.
  62. */
  63. void setValueAsCompleteGesture (float newDenormalisedValue);
  64. /** Begins a gesture on the managed parameter.
  65. Call this when the UI is about to begin a continuous interaction,
  66. like when the mouse button is pressed on a slider.
  67. */
  68. void beginGesture();
  69. /** Updates the parameter value during a gesture.
  70. Call this during a continuous interaction, like a slider value
  71. changed callback.
  72. */
  73. void setValueAsPartOfGesture (float newDenormalisedValue);
  74. /** Ends a gesture on the managed parameter.
  75. Call this when the UI has finished a continuous interaction,
  76. like when the mouse button is released on a slider.
  77. */
  78. void endGesture();
  79. private:
  80. float normalise (float f) const { return parameter.convertTo0to1 (f); }
  81. template <typename Callback>
  82. void callIfParameterValueChanged (float newDenormalisedValue, Callback&& callback);
  83. void parameterValueChanged (int, float) override;
  84. void parameterGestureChanged (int, bool) override {}
  85. void handleAsyncUpdate() override;
  86. RangedAudioParameter& parameter;
  87. std::atomic<float> lastValue { 0.0f };
  88. UndoManager* undoManager = nullptr;
  89. std::function<void (float)> setValue;
  90. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterAttachment)
  91. };
  92. //==============================================================================
  93. /** An object of this class maintains a connection between a Slider and a
  94. plug-in parameter.
  95. During the lifetime of this object it keeps the two things in sync, making
  96. it easy to connect a slider to a parameter. When this object is deleted, the
  97. connection is broken. Make sure that your parameter and Slider are not
  98. deleted before this object!
  99. @tags{Audio}
  100. */
  101. class SliderParameterAttachment : private Slider::Listener
  102. {
  103. public:
  104. /** Creates a connection between a plug-in parameter and a Slider.
  105. @param parameter The parameter to use
  106. @param slider The Slider to use
  107. @param undoManager An optional UndoManager
  108. */
  109. SliderParameterAttachment (RangedAudioParameter& parameter, Slider& slider,
  110. UndoManager* undoManager = nullptr);
  111. /** Destructor. */
  112. ~SliderParameterAttachment() override;
  113. /** Call this after setting up your slider in the case where you need to do
  114. extra setup after constructing this attachment.
  115. */
  116. void sendInitialUpdate();
  117. private:
  118. void setValue (float newValue);
  119. void sliderValueChanged (Slider*) override;
  120. void sliderDragStarted (Slider*) override { attachment.beginGesture(); }
  121. void sliderDragEnded (Slider*) override { attachment.endGesture(); }
  122. Slider& slider;
  123. ParameterAttachment attachment;
  124. bool ignoreCallbacks = false;
  125. };
  126. //==============================================================================
  127. /** An object of this class maintains a connection between a ComboBox and a
  128. plug-in parameter.
  129. ComboBox items will be spaced linearly across the range of the parameter. For
  130. example if the range is specified by NormalisableRange<float> (-0.5f, 0.5f, 0.5f)
  131. and you add three items then the first will be mapped to a value of -0.5, the
  132. second to 0, and the third to 0.5.
  133. During the lifetime of this object it keeps the two things in sync, making it
  134. easy to connect a combo box to a parameter. When this object is deleted, the
  135. connection is broken. Make sure that your parameter and ComboBox are not deleted
  136. before this object!
  137. @tags{Audio}
  138. */
  139. class ComboBoxParameterAttachment : private ComboBox::Listener
  140. {
  141. public:
  142. /** Creates a connection between a plug-in parameter and a ComboBox.
  143. @param parameter The parameter to use
  144. @param combo The ComboBox to use
  145. @param undoManager An optional UndoManager
  146. */
  147. ComboBoxParameterAttachment (RangedAudioParameter& parameter, ComboBox& combo,
  148. UndoManager* undoManager = nullptr);
  149. /** Destructor. */
  150. ~ComboBoxParameterAttachment() override;
  151. /** Call this after setting up your combo box in the case where you need to do
  152. extra setup after constructing this attachment.
  153. */
  154. void sendInitialUpdate();
  155. private:
  156. void setValue (float newValue);
  157. void comboBoxChanged (ComboBox*) override;
  158. ComboBox& comboBox;
  159. RangedAudioParameter& storedParameter;
  160. ParameterAttachment attachment;
  161. bool ignoreCallbacks = false;
  162. };
  163. //==============================================================================
  164. /** An object of this class maintains a connection between a Button and a
  165. plug-in parameter.
  166. During the lifetime of this object it keeps the two things in sync, making it
  167. easy to connect a button to a parameter. When this object is deleted, the
  168. connection is broken. Make sure that your parameter and Button are not deleted
  169. before this object!
  170. @tags{Audio}
  171. */
  172. class ButtonParameterAttachment : private Button::Listener
  173. {
  174. public:
  175. /** Creates a connection between a plug-in parameter and a Button.
  176. @param parameter The parameter to use
  177. @param button The Button to use
  178. @param undoManager An optional UndoManager
  179. */
  180. ButtonParameterAttachment (RangedAudioParameter& parameter, Button& button,
  181. UndoManager* undoManager = nullptr);
  182. /** Destructor. */
  183. ~ButtonParameterAttachment() override;
  184. /** Call this after setting up your button in the case where you need to do
  185. extra setup after constructing this attachment.
  186. */
  187. void sendInitialUpdate();
  188. private:
  189. void setValue (float newValue);
  190. void buttonClicked (Button*) override;
  191. Button& button;
  192. ParameterAttachment attachment;
  193. bool ignoreCallbacks = false;
  194. };
  195. } // namespace juce