1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/examples/MPETest/Source/MPESetupComponent.h

335 lines
14 KiB
C++

/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2015 - ROLI Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef MPESETUPCOMPONENT_H_INCLUDED
#define MPESETUPCOMPONENT_H_INCLUDED
class MPESetupComponent : public Component,
public ChangeBroadcaster,
private Button::Listener,
private ComboBox::Listener
{
public:
//==============================================================================
class Listener
{
public:
virtual ~Listener() {}
virtual void zoneAdded (MPEZone newZone) = 0;
virtual void allZonesCleared() = 0;
virtual void legacyModeChanged (bool legacyModeEnabled, int pitchbendRange, Range<int> channelRange) = 0;
virtual void voiceStealingEnabledChanged (bool voiceStealingEnabled) = 0;
virtual void numberOfVoicesChanged (int numberOfVoices) = 0;
};
void addListener (Listener* listenerToAdd) { listeners.add (listenerToAdd); }
void removeListener (Listener* listenerToRemove) { listeners.remove (listenerToRemove); }
//==============================================================================
MPESetupComponent()
: masterChannelLabel (String(), "Master channel:"),
noteChannelsLabel (String(), "Nr. of note channels:"),
masterPitchbendRangeLabel (String(), "Master pitchbend range (semitones):"),
notePitchbendRangeLabel (String(), "Note pitchbend range (semitones):"),
addZoneButton ("Add this zone"),
clearAllZonesButton ("Clear all zones"),
legacyStartChannelLabel (String(), "First channel:"),
legacyEndChannelLabel (String(), "Last channel:"),
legacyPitchbendRangeLabel (String(), "Pitchbend range (semitones):"),
legacyModeEnabledToggle ("Enable Legacy Mode"),
voiceStealingEnabledToggle ("Enable synth voice stealing"),
numberOfVoicesLabel (String(), "Number of synth voices")
{
initialiseComboBoxWithConsecutiveIntegers (masterChannel, masterChannelLabel, 1, 15, defaultMasterChannel);
initialiseComboBoxWithConsecutiveIntegers (noteChannels, noteChannelsLabel, 1, 15, defaultNoteChannels);
initialiseComboBoxWithConsecutiveIntegers (masterPitchbendRange, masterPitchbendRangeLabel, 0, 96, defaultMasterPitchbendRange);
initialiseComboBoxWithConsecutiveIntegers (notePitchbendRange, notePitchbendRangeLabel, 0, 96, defaultNotePitchbendRange);
initialiseComboBoxWithConsecutiveIntegers (legacyStartChannel, legacyStartChannelLabel, 1, 16, 1, false);
initialiseComboBoxWithConsecutiveIntegers (legacyEndChannel, legacyEndChannelLabel, 1, 16, 16, false);
initialiseComboBoxWithConsecutiveIntegers (legacyPitchbendRange, legacyPitchbendRangeLabel, 0, 96, 2, false);
initialiseButton (addZoneButton);
initialiseButton (clearAllZonesButton);
initialiseButton (legacyModeEnabledToggle);
initialiseButton (voiceStealingEnabledToggle);
initialiseComboBoxWithConsecutiveIntegers (numberOfVoices, numberOfVoicesLabel, 1, 20, 15);
numberOfVoices.addListener (this);
}
//==============================================================================
void resized() override
{
Rectangle<int> r (proportionOfWidth (0.65f), 15, proportionOfWidth (0.25f), 3000);
const int h = 24;
const int hspace = 6;
const int hbigspace = 18;
masterChannel.setBounds (r.removeFromTop (h));
r.removeFromTop (hspace);
noteChannels.setBounds (r.removeFromTop (h));
r.removeFromTop (hspace);
notePitchbendRange.setBounds (r.removeFromTop (h));
r.removeFromTop (hspace);
masterPitchbendRange.setBounds (r.removeFromTop (h));
legacyStartChannel.setBounds (masterChannel.getBounds());
legacyEndChannel.setBounds (noteChannels.getBounds());
legacyPitchbendRange.setBounds (notePitchbendRange.getBounds());
r.removeFromTop (hbigspace);
int buttonLeft = proportionOfWidth (0.5f);
addZoneButton.setBounds (r.removeFromTop (h).withLeft (buttonLeft));
r.removeFromTop (hspace);
clearAllZonesButton.setBounds (r.removeFromTop (h).withLeft (buttonLeft));
r.removeFromTop (hbigspace);
int toggleLeft = proportionOfWidth (0.25f);
legacyModeEnabledToggle.setBounds (r.removeFromTop (h).withLeft (toggleLeft));
r.removeFromTop (hspace);
voiceStealingEnabledToggle.setBounds (r.removeFromTop (h).withLeft (toggleLeft));
r.removeFromTop (hspace);
numberOfVoices.setBounds (r.removeFromTop (h));
}
private:
//==============================================================================
void initialiseComboBoxWithConsecutiveIntegers (ComboBox& comboBox, Label& labelToAttach,
int firstValue, int numValues, int valueToSelect,
bool makeVisible = true)
{
for (int i = 0; i < numValues; ++i)
comboBox.addItem (String (i + firstValue), i + 1);
comboBox.setSelectedId (valueToSelect - firstValue + 1);
labelToAttach.attachToComponent (&comboBox, true);
if (makeVisible)
addAndMakeVisible (comboBox);
else
addChildComponent (comboBox);
comboBox.addListener (this);
}
//==============================================================================
void initialiseButton (Button& button)
{
addAndMakeVisible (button);
button.addListener (this);
}
//==============================================================================
void buttonClicked (Button* button) override
{
if (button == &addZoneButton)
addZoneButtonClicked();
else if (button == &clearAllZonesButton)
clearAllZonesButtonClicked();
else if (button == &legacyModeEnabledToggle)
legacyModeEnabledToggleClicked();
else if (button == &voiceStealingEnabledToggle)
voiceStealingEnabledToggleClicked();
}
//==============================================================================
void addZoneButtonClicked()
{
if (areMPEParametersValid())
{
MPEZone newZone (masterChannel.getText().getIntValue(),
noteChannels.getText().getIntValue(),
notePitchbendRange.getText().getIntValue(),
masterPitchbendRange.getText().getIntValue());
zoneLayout.addZone (newZone);
listeners.call (&MPESetupComponent::Listener::zoneAdded, newZone);
}
else
{
handleInvalidMPEParameters();
}
}
//==============================================================================
void clearAllZonesButtonClicked()
{
zoneLayout.clearAllZones();
listeners.call (&MPESetupComponent::Listener::allZonesCleared);
}
//==============================================================================
void legacyModeEnabledToggleClicked()
{
bool legacyModeEnabled = legacyModeEnabledToggle.getToggleState();
masterChannel.setVisible (! legacyModeEnabled);
noteChannels.setVisible (! legacyModeEnabled);
notePitchbendRange.setVisible (! legacyModeEnabled);
masterPitchbendRange.setVisible (! legacyModeEnabled);
addZoneButton.setVisible (! legacyModeEnabled);
clearAllZonesButton.setVisible (! legacyModeEnabled);
legacyStartChannel.setVisible (legacyModeEnabled);
legacyEndChannel.setVisible (legacyModeEnabled);
legacyPitchbendRange.setVisible (legacyModeEnabled);
if (areLegacyModeParametersValid())
{
listeners.call (&MPESetupComponent::Listener::legacyModeChanged,
legacyModeEnabledToggle.getToggleState(),
legacyPitchbendRange.getText().getIntValue(),
getLegacyModeChannelRange());
}
else
{
handleInvalidLegacyModeParameters();
}
}
//==============================================================================
void voiceStealingEnabledToggleClicked()
{
listeners.call (&MPESetupComponent::Listener::voiceStealingEnabledChanged,
voiceStealingEnabledToggle.getToggleState());
}
//==============================================================================
void comboBoxChanged (ComboBox* comboBoxThatHasChanged) override
{
if (comboBoxThatHasChanged == &numberOfVoices)
{
numberOfVoicesChanged();
}
else if (legacyModeEnabledToggle.getToggleState() == true)
{
if (comboBoxThatHasChanged == &legacyPitchbendRange)
legacyModePitchbendRangeChanged();
else if (comboBoxThatHasChanged == &legacyStartChannel || comboBoxThatHasChanged == &legacyEndChannel)
legacyModeChannelRangeChanged();
}
}
//==============================================================================
void numberOfVoicesChanged()
{
listeners.call (&MPESetupComponent::Listener::numberOfVoicesChanged,
numberOfVoices.getText().getIntValue());
}
void legacyModePitchbendRangeChanged()
{
jassert (legacyModeEnabledToggle.getToggleState() == true);
listeners.call (&MPESetupComponent::Listener::legacyModeChanged, true,
legacyPitchbendRange.getText().getIntValue(),
getLegacyModeChannelRange());
}
void legacyModeChannelRangeChanged()
{
jassert (legacyModeEnabledToggle.getToggleState() == true);
if (areLegacyModeParametersValid())
{
listeners.call (&MPESetupComponent::Listener::legacyModeChanged, true,
legacyPitchbendRange.getText().getIntValue(),
getLegacyModeChannelRange());
}
else
{
handleInvalidLegacyModeParameters();
}
}
//==============================================================================
bool areMPEParametersValid() const
{
int maxPossibleNumNoteChannels = 16 - masterChannel.getText().getIntValue();
return noteChannels.getText().getIntValue() <= maxPossibleNumNoteChannels;
}
void handleInvalidMPEParameters() const
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Invalid zone layout",
"Cannot create MPE zone:\n"
"Invalid zone parameters selected!",
"Got it");
}
bool areLegacyModeParametersValid() const
{
return legacyStartChannel.getText().getIntValue() <= legacyEndChannel.getText().getIntValue();
}
void handleInvalidLegacyModeParameters() const
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Invalid legacy mode channel layout",
"Cannot set legacy mode start/end channel:\n"
"The end channel must not be less than the start channel!",
"Got it");
}
//==============================================================================
Range<int> getLegacyModeChannelRange() const
{
return Range<int> (legacyStartChannel.getText().getIntValue(),
legacyEndChannel.getText().getIntValue() + 1);
}
//==============================================================================
MPEZoneLayout zoneLayout;
ComboBox masterChannel, noteChannels, masterPitchbendRange, notePitchbendRange;
Label masterChannelLabel, noteChannelsLabel, masterPitchbendRangeLabel, notePitchbendRangeLabel;
TextButton addZoneButton, clearAllZonesButton;
ComboBox legacyStartChannel, legacyEndChannel, legacyPitchbendRange;
Label legacyStartChannelLabel, legacyEndChannelLabel, legacyPitchbendRangeLabel;
ToggleButton legacyModeEnabledToggle, voiceStealingEnabledToggle;
ComboBox numberOfVoices;
Label numberOfVoicesLabel;
ListenerList<Listener> listeners;
const int defaultMasterChannel = 1, defaultNoteChannels = 15,
defaultMasterPitchbendRange = 2, defaultNotePitchbendRange = 48;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESetupComponent)
};
#endif // MPESETUPCOMPONENT_H_INCLUDED