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.

260 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI 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. #ifndef MPESETUPCOMPONENT_H_INCLUDED
  18. #define MPESETUPCOMPONENT_H_INCLUDED
  19. class MPESetupComponent : public Component,
  20. public ChangeBroadcaster,
  21. private Button::Listener,
  22. private ComboBox::Listener
  23. {
  24. public:
  25. //==========================================================================
  26. class Listener
  27. {
  28. public:
  29. virtual ~Listener() {}
  30. virtual void zoneAdded (MPEZone newZone) = 0;
  31. virtual void allZonesCleared() = 0;
  32. virtual void omniModeChanged (bool omniModeEnabled, int pitchbendRange) = 0;
  33. virtual void voiceStealingEnabledChanged (bool voiceStealingEnabled) = 0;
  34. virtual void numberOfVoicesChanged (int numberOfVoices) = 0;
  35. };
  36. void addListener (Listener* listenerToAdd) { listeners.add (listenerToAdd); }
  37. void removeListener (Listener* listenerToRemove) { listeners.remove (listenerToRemove); }
  38. //==========================================================================
  39. MPESetupComponent()
  40. : masterChannelLabel (String::empty, "Master channel:"),
  41. noteChannelsLabel (String::empty, "Nr. of note channels:"),
  42. masterPitchbendRangeLabel (String::empty, "Master pitchbend range (semitones):"),
  43. notePitchbendRangeLabel (String::empty, "Note pitchbend range (semitones):"),
  44. addZoneButton ("Add this zone"),
  45. clearAllZonesButton ("Clear all zones"),
  46. omniModeEnabledToggle ("Enable Omni Mode"),
  47. voiceStealingEnabledToggle ("Enable synth voice stealing"),
  48. numberOfVoicesLabel (String::empty, "Number of synth voices")
  49. {
  50. initialiseComboBoxWithConsecutiveIntegers (masterChannel, masterChannelLabel, 1, 15, defaultMasterChannel);
  51. initialiseComboBoxWithConsecutiveIntegers (noteChannels, noteChannelsLabel, 1, 15, defaultNoteChannels);
  52. initialiseComboBoxWithConsecutiveIntegers (masterPitchbendRange, masterPitchbendRangeLabel, 0, 96, defaultMasterPitchbendRange);
  53. initialiseComboBoxWithConsecutiveIntegers (notePitchbendRange, notePitchbendRangeLabel, 0, 96, defaultNotePitchbendRange);
  54. notePitchbendRange.addListener (this);
  55. initialiseButton (addZoneButton);
  56. initialiseButton (clearAllZonesButton);
  57. initialiseButton (omniModeEnabledToggle);
  58. initialiseButton (voiceStealingEnabledToggle);
  59. initialiseComboBoxWithConsecutiveIntegers (numberOfVoices, numberOfVoicesLabel, 1, 20, 15);
  60. numberOfVoices.addListener (this);
  61. }
  62. //==========================================================================
  63. void resized() override
  64. {
  65. Rectangle<int> r (proportionOfWidth (0.65f), 15, proportionOfWidth (0.25f), 3000);
  66. const int h = 24;
  67. const int hspace = 6;
  68. const int hbigspace = 18;
  69. masterChannel.setBounds (r.removeFromTop (h));
  70. r.removeFromTop (hspace);
  71. noteChannels.setBounds (r.removeFromTop (h));
  72. r.removeFromTop (hspace);
  73. masterPitchbendRange.setBounds (r.removeFromTop (h));
  74. r.removeFromTop (hspace);
  75. notePitchbendRange.setBounds (r.removeFromTop (h));
  76. r.removeFromTop (hbigspace);
  77. int buttonLeft = proportionOfWidth (0.5f);
  78. addZoneButton.setBounds (r.removeFromTop (h).withLeft (buttonLeft));
  79. r.removeFromTop (hspace);
  80. clearAllZonesButton.setBounds (r.removeFromTop (h).withLeft (buttonLeft));
  81. r.removeFromTop (hbigspace);
  82. int toggleLeft = proportionOfWidth (0.25f);
  83. omniModeEnabledToggle.setBounds (r.removeFromTop (h).withLeft (toggleLeft));
  84. r.removeFromTop (hspace);
  85. voiceStealingEnabledToggle.setBounds (r.removeFromTop (h).withLeft (toggleLeft));
  86. r.removeFromTop (hspace);
  87. numberOfVoices.setBounds (r.removeFromTop (h));
  88. }
  89. private:
  90. //==========================================================================
  91. void initialiseComboBoxWithConsecutiveIntegers (ComboBox& comboBox, Label& labelToAttach,
  92. int firstValue, int numValues, int valueToSelect)
  93. {
  94. addAndMakeVisible (comboBox);
  95. for (int i = 0; i < numValues; ++i)
  96. comboBox.addItem (String (i + firstValue), i + 1);
  97. comboBox.setSelectedId (valueToSelect - firstValue + 1);
  98. labelToAttach.attachToComponent (&comboBox, true);
  99. }
  100. //==========================================================================
  101. void initialiseButton (Button& button)
  102. {
  103. addAndMakeVisible (button);
  104. button.addListener (this);
  105. }
  106. //==========================================================================
  107. void buttonClicked (Button* button) override
  108. {
  109. if (button == &addZoneButton)
  110. addZoneButtonClicked();
  111. else if (button == &clearAllZonesButton)
  112. clearAllZonesButtonClicked();
  113. else if (button == &omniModeEnabledToggle)
  114. omniModeEnabledToggleClicked();
  115. else if (button == &voiceStealingEnabledToggle)
  116. voiceStealingEnabledToggleClicked();
  117. }
  118. //==========================================================================
  119. void addZoneButtonClicked()
  120. {
  121. if (selectedZoneParametersValid())
  122. {
  123. MPEZone newZone (masterChannel.getText().getIntValue(),
  124. noteChannels.getText().getIntValue(),
  125. notePitchbendRange.getText().getIntValue(),
  126. masterPitchbendRange.getText().getIntValue());
  127. zoneLayout.addZone (newZone);
  128. listeners.call (&MPESetupComponent::Listener::zoneAdded, newZone);
  129. }
  130. else
  131. {
  132. handleInvalidNrOfNoteChannels();
  133. }
  134. }
  135. //==========================================================================
  136. void clearAllZonesButtonClicked()
  137. {
  138. zoneLayout.clearAllZones();
  139. listeners.call (&MPESetupComponent::Listener::allZonesCleared);
  140. }
  141. //==========================================================================
  142. void omniModeEnabledToggleClicked()
  143. {
  144. bool omniModeEnabled = omniModeEnabledToggle.getToggleState();
  145. masterChannel.setEnabled (! omniModeEnabled);
  146. noteChannels.setEnabled (! omniModeEnabled);
  147. masterPitchbendRange.setEnabled (! omniModeEnabled);
  148. addZoneButton.setEnabled (! omniModeEnabled);
  149. clearAllZonesButton.setEnabled (! omniModeEnabled);
  150. listeners.call (&MPESetupComponent::Listener::omniModeChanged,
  151. omniModeEnabledToggle.getToggleState(),
  152. notePitchbendRange.getText().getIntValue());
  153. }
  154. //==========================================================================
  155. void voiceStealingEnabledToggleClicked()
  156. {
  157. listeners.call (&MPESetupComponent::Listener::voiceStealingEnabledChanged,
  158. voiceStealingEnabledToggle.getToggleState());
  159. }
  160. //==========================================================================
  161. void comboBoxChanged (ComboBox* comboBoxThatHasChanged) override
  162. {
  163. if (comboBoxThatHasChanged == &numberOfVoices)
  164. numberOfVoicesChanged();
  165. else if (comboBoxThatHasChanged == &notePitchbendRange && omniModeEnabledToggle.getToggleState() == true)
  166. omniModePitchbendRangeChanged();
  167. }
  168. //==========================================================================
  169. void numberOfVoicesChanged()
  170. {
  171. listeners.call (&MPESetupComponent::Listener::numberOfVoicesChanged,
  172. numberOfVoices.getText().getIntValue());
  173. }
  174. void omniModePitchbendRangeChanged()
  175. {
  176. jassert (omniModeEnabledToggle.getToggleState() == true);
  177. listeners.call (&MPESetupComponent::Listener::omniModeChanged, true,
  178. notePitchbendRange.getText().getIntValue());
  179. }
  180. //==========================================================================
  181. bool selectedZoneParametersValid() const
  182. {
  183. int maxPossibleNumNoteChannels = 16 - masterChannel.getText().getIntValue();
  184. return noteChannels.getText().getIntValue() <= maxPossibleNumNoteChannels;
  185. }
  186. //==========================================================================
  187. void handleInvalidNrOfNoteChannels() const
  188. {
  189. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  190. "Invalid zone layout",
  191. "Cannot create MPE zone:\n"
  192. "Invalid zone parameters selected!",
  193. "Got it");
  194. }
  195. //==========================================================================
  196. MPEZoneLayout zoneLayout;
  197. ComboBox masterChannel, noteChannels, masterPitchbendRange, notePitchbendRange;
  198. Label masterChannelLabel, noteChannelsLabel, masterPitchbendRangeLabel, notePitchbendRangeLabel;
  199. TextButton addZoneButton, clearAllZonesButton;
  200. ToggleButton omniModeEnabledToggle, voiceStealingEnabledToggle;
  201. ComboBox numberOfVoices;
  202. Label numberOfVoicesLabel;
  203. ListenerList<Listener> listeners;
  204. const int defaultMasterChannel = 1, defaultNoteChannels = 15,
  205. defaultMasterPitchbendRange = 2, defaultNotePitchbendRange = 48;
  206. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESetupComponent)
  207. };
  208. #endif // MPESETUPCOMPONENT_H_INCLUDED