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

Used Button::onClick to simplify a bunch of library classes and demo code

This commit is contained in:
jules 2018-01-03 10:45:13 +00:00
parent be5f2d62c4
commit ce8b2d865a
52 changed files with 557 additions and 954 deletions

View file

@ -27,14 +27,12 @@
namespace juce
{
class SimpleDeviceManagerInputLevelMeter : public Component,
public Timer
struct SimpleDeviceManagerInputLevelMeter : public Component,
public Timer
{
public:
SimpleDeviceManagerInputLevelMeter (AudioDeviceManager& m)
: manager (m), level (0)
SimpleDeviceManagerInputLevelMeter (AudioDeviceManager& m) : manager (m)
{
startTimer (50);
startTimerHz (20);
manager.enableInputLevelMeasurement (true);
}
@ -47,7 +45,7 @@ public:
{
if (isShowing())
{
const float newLevel = (float) manager.getCurrentInputLevel();
auto newLevel = (float) manager.getCurrentInputLevel();
if (std::abs (level - newLevel) > 0.005f)
{
@ -67,9 +65,8 @@ public:
(float) exp (log (level) / 3.0)); // (add a bit of a skew to make the level more obvious)
}
private:
AudioDeviceManager& manager;
float level;
float level = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleDeviceManagerInputLevelMeter)
};
@ -81,7 +78,7 @@ class AudioDeviceSelectorComponent::MidiInputSelectorComponentListBox : public
{
public:
MidiInputSelectorComponentListBox (AudioDeviceManager& dm, const String& noItems)
: ListBox (String(), nullptr),
: ListBox ({}, nullptr),
deviceManager (dm),
noItemsMessage (noItems)
{
@ -108,11 +105,11 @@ public:
g.fillAll (findColour (TextEditor::highlightColourId)
.withMultipliedAlpha (0.3f));
const String item (items [row]);
auto item = items[row];
bool enabled = deviceManager.isMidiInputEnabled (item);
const int x = getTickX();
const float tickW = height * 0.75f;
auto x = getTickX();
auto tickW = height * 0.75f;
getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW,
enabled, true, true, false);
@ -145,7 +142,7 @@ public:
{
ListBox::paint (g);
if (items.size() == 0)
if (items.isEmpty())
{
g.setColour (Colours::grey);
g.setFont (13.0f);
@ -155,9 +152,9 @@ public:
}
}
int getBestHeight (const int preferredHeight)
int getBestHeight (int preferredHeight)
{
const int extra = getOutlineThickness() * 2;
auto extra = getOutlineThickness() * 2;
return jmax (getRowHeight() * 2 + extra,
jmin (getRowHeight() * getNumRows() + extra,
@ -174,7 +171,7 @@ private:
{
if (isPositiveAndBelow (row, items.size()))
{
const String item (items [row]);
auto item = items[row];
deviceManager.setMidiInputEnabled (item, ! deviceManager.isMidiInputEnabled (item));
}
}
@ -202,8 +199,7 @@ static String getNoDeviceString() { return "<< " + TRANS("none") + " >>"; }
//==============================================================================
class AudioDeviceSettingsPanel : public Component,
private ChangeListener,
private ComboBox::Listener,
private Button::Listener
private ComboBox::Listener
{
public:
AudioDeviceSettingsPanel (AudioIODeviceType& t, AudioDeviceSetupDetails& setupDetails,
@ -213,7 +209,7 @@ public:
if (hideAdvancedOptionsWithButton)
{
addAndMakeVisible (showAdvancedSettingsButton = new TextButton (TRANS("Show advanced settings...")));
showAdvancedSettingsButton->addListener (this);
showAdvancedSettingsButton->onClick = [this]() { showAdvanced(); };
}
type.scanForDevices();
@ -228,7 +224,7 @@ public:
void resized() override
{
if (AudioDeviceSelectorComponent* parent = findParentComponentOfClass<AudioDeviceSelectorComponent>())
if (auto* parent = findParentComponentOfClass<AudioDeviceSelectorComponent>())
{
Rectangle<int> r (proportionOfWidth (0.35f), 0, proportionOfWidth (0.6f), 3000);
@ -238,7 +234,7 @@ public:
if (outputDeviceDropDown != nullptr)
{
Rectangle<int> row (r.removeFromTop (h));
auto row = r.removeFromTop (h);
if (testButton != nullptr)
{
@ -253,7 +249,7 @@ public:
if (inputDeviceDropDown != nullptr)
{
Rectangle<int> row (r.removeFromTop (h));
auto row = r.removeFromTop (h);
inputLevelMeter->setBounds (row.removeFromRight (testButton != nullptr ? testButton->getWidth() : row.getWidth() / 6));
row.removeFromRight (space);
@ -304,7 +300,7 @@ public:
if (showUIButton != nullptr || resetDeviceButton != nullptr)
{
Rectangle<int> buttons (r.removeFromTop (h));
auto buttons = r.removeFromTop (h);
if (showUIButton != nullptr)
{
@ -393,7 +389,7 @@ public:
bool showDeviceControlPanel()
{
if (AudioIODevice* const device = setup.manager->getCurrentAudioDevice())
if (auto* device = setup.manager->getCurrentAudioDevice())
{
Component modalWindow;
modalWindow.setOpaque (true);
@ -406,32 +402,27 @@ public:
return false;
}
void buttonClicked (Button* button) override
void showAdvanced()
{
if (button == showAdvancedSettingsButton)
showAdvancedSettingsButton->setVisible (false);
resized();
}
void showDeviceUIPanel()
{
if (showDeviceControlPanel())
{
showAdvancedSettingsButton->setVisible (false);
resized();
}
else if (button == showUIButton)
{
if (showDeviceControlPanel())
{
setup.manager->closeAudioDevice();
setup.manager->restartLastAudioDevice();
getTopLevelComponent()->toFront (true);
}
}
else if (button == testButton && testButton != nullptr)
{
setup.manager->playTestSound();
}
else if (button == resetDeviceButton)
{
resetDevice();
setup.manager->closeAudioDevice();
setup.manager->restartLastAudioDevice();
getTopLevelComponent()->toFront (true);
}
}
void playTestSound()
{
setup.manager->playTestSound();
}
void updateAllControls()
{
updateOutputsComboBox();
@ -440,7 +431,7 @@ public:
updateControlPanelButton();
updateResetButton();
if (AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice())
if (auto* currentDevice = setup.manager->getCurrentAudioDevice())
{
if (setup.maxNumOutputChannels > 0
&& setup.minNumOutputChannels < setup.manager->getCurrentAudioDevice()->getOutputChannelNames().size())
@ -450,7 +441,7 @@ public:
addAndMakeVisible (outputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType,
TRANS ("(no audio output channels found)")));
outputChanLabel = new Label (String(), TRANS("Active output channels:"));
outputChanLabel = new Label ({}, TRANS("Active output channels:"));
outputChanLabel->setJustificationType (Justification::centredRight);
outputChanLabel->attachToComponent (outputChanList, true);
}
@ -471,7 +462,7 @@ public:
addAndMakeVisible (inputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType,
TRANS("(no audio input channels found)")));
inputChanLabel = new Label (String(), TRANS("Active input channels:"));
inputChanLabel = new Label ({}, TRANS("Active input channels:"));
inputChanLabel->setJustificationType (Justification::centredRight);
inputChanLabel->attachToComponent (inputChanList, true);
}
@ -534,13 +525,12 @@ private:
ScopedPointer<Component> inputLevelMeter;
ScopedPointer<TextButton> showUIButton, showAdvancedSettingsButton, resetDeviceButton;
void showCorrectDeviceName (ComboBox* const box, const bool isInput)
void showCorrectDeviceName (ComboBox* box, bool isInput)
{
if (box != nullptr)
{
AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice();
const int index = type.getIndexOfDevice (currentDevice, isInput);
auto* currentDevice = setup.manager->getCurrentAudioDevice();
auto index = type.getIndexOfDevice (currentDevice, isInput);
box->setSelectedId (index + 1, dontSendNotification);
@ -581,7 +571,7 @@ private:
{
addAndMakeVisible (showUIButton = new TextButton (TRANS ("Control Panel"),
TRANS ("Opens the device's own control panel")));
showUIButton->addListener (this);
showUIButton->onClick = [this]() { showDeviceUIPanel(); };
}
resized();
@ -589,7 +579,7 @@ private:
void updateResetButton()
{
if (AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice())
if (auto* currentDevice = setup.manager->getCurrentAudioDevice())
{
if (currentDevice->hasControlPanel())
{
@ -598,7 +588,7 @@ private:
addAndMakeVisible (resetDeviceButton = new TextButton (TRANS ("Reset Device"),
TRANS ("Resets the audio interface - sometimes needed after changing a device's properties in its custom control panel")));
resetDeviceButton->addListener (this);
resetDeviceButton->onClick = [this]() { resetDevice(); };
resized();
}
@ -615,20 +605,19 @@ private:
{
if (outputDeviceDropDown == nullptr)
{
outputDeviceDropDown = new ComboBox (String());
outputDeviceDropDown = new ComboBox();
outputDeviceDropDown->addListener (this);
addAndMakeVisible (outputDeviceDropDown);
outputDeviceLabel = new Label (String(),
type.hasSeparateInputsAndOutputs() ? TRANS("Output:")
: TRANS("Device:"));
outputDeviceLabel = new Label ({}, type.hasSeparateInputsAndOutputs() ? TRANS("Output:")
: TRANS("Device:"));
outputDeviceLabel->attachToComponent (outputDeviceDropDown, true);
if (setup.maxNumOutputChannels > 0)
{
addAndMakeVisible (testButton = new TextButton (TRANS("Test"),
TRANS("Plays a test tone")));
testButton->addListener (this);
testButton->onClick = [this]() { playTestSound(); };
}
}
@ -644,11 +633,11 @@ private:
{
if (inputDeviceDropDown == nullptr)
{
inputDeviceDropDown = new ComboBox (String());
inputDeviceDropDown = new ComboBox();
inputDeviceDropDown->addListener (this);
addAndMakeVisible (inputDeviceDropDown);
inputDeviceLabel = new Label (String(), TRANS("Input:"));
inputDeviceLabel = new Label ({}, TRANS("Input:"));
inputDeviceLabel->attachToComponent (inputDeviceDropDown, true);
addAndMakeVisible (inputLevelMeter
@ -665,9 +654,9 @@ private:
{
if (sampleRateDropDown == nullptr)
{
addAndMakeVisible (sampleRateDropDown = new ComboBox (String()));
addAndMakeVisible (sampleRateDropDown = new ComboBox());
sampleRateLabel = new Label (String(), TRANS("Sample rate:"));
sampleRateLabel = new Label ({}, TRANS("Sample rate:"));
sampleRateLabel->attachToComponent (sampleRateDropDown, true);
}
else
@ -676,12 +665,10 @@ private:
sampleRateDropDown->removeListener (this);
}
const Array<double> rates (currentDevice->getAvailableSampleRates());
for (int i = 0; i < rates.size(); ++i)
for (auto rate : currentDevice->getAvailableSampleRates())
{
const int rate = roundToInt (rates[i]);
sampleRateDropDown->addItem (String (rate) + " Hz", rate);
auto intRate = roundToInt (rate);
sampleRateDropDown->addItem (String (intRate) + " Hz", intRate);
}
sampleRateDropDown->setSelectedId (roundToInt (currentDevice->getCurrentSampleRate()), dontSendNotification);
@ -692,9 +679,9 @@ private:
{
if (bufferSizeDropDown == nullptr)
{
addAndMakeVisible (bufferSizeDropDown = new ComboBox (String()));
addAndMakeVisible (bufferSizeDropDown = new ComboBox());
bufferSizeLabel = new Label (String(), TRANS("Audio buffer size:"));
bufferSizeLabel = new Label ({}, TRANS("Audio buffer size:"));
bufferSizeLabel->attachToComponent (bufferSizeDropDown, true);
}
else
@ -703,17 +690,13 @@ private:
bufferSizeDropDown->removeListener (this);
}
const Array<int> bufferSizes (currentDevice->getAvailableBufferSizes());
auto currentRate = currentDevice->getCurrentSampleRate();
double currentRate = currentDevice->getCurrentSampleRate();
if (currentRate == 0)
currentRate = 48000.0;
for (int i = 0; i < bufferSizes.size(); ++i)
{
const int bs = bufferSizes[i];
for (auto bs : currentDevice->getAvailableBufferSizes())
bufferSizeDropDown->addItem (String (bs) + " samples (" + String (bs * 1000.0 / currentRate, 1) + " ms)", bs);
}
bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), dontSendNotification);
bufferSizeDropDown->addListener (this);
@ -732,10 +715,8 @@ public:
};
//==============================================================================
ChannelSelectorListBox (const AudioDeviceSetupDetails& setupDetails,
const BoxType boxType, const String& noItemsText)
: ListBox (String(), nullptr),
setup (setupDetails), type (boxType), noItemsMessage (noItemsText)
ChannelSelectorListBox (const AudioDeviceSetupDetails& setupDetails, BoxType boxType, const String& noItemsText)
: ListBox ({}, nullptr), setup (setupDetails), type (boxType), noItemsMessage (noItemsText)
{
refresh();
setModel (this);
@ -746,7 +727,7 @@ public:
{
items.clear();
if (AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice())
if (auto* currentDevice = setup.manager->getCurrentAudioDevice())
{
if (type == audioInputType)
items = currentDevice->getInputChannelNames();
@ -759,7 +740,7 @@ public:
for (int i = 0; i < items.size(); i += 2)
{
const String& name = items[i];
auto& name = items[i];
if (i + 1 >= items.size())
pairs.add (name.trim());
@ -786,7 +767,7 @@ public:
{
g.fillAll (findColour (ListBox::backgroundColourId));
const String item (items [row]);
auto item = items[row];
bool enabled = false;
AudioDeviceManager::AudioDeviceSetup config;
@ -795,20 +776,20 @@ public:
if (setup.useStereoPairs)
{
if (type == audioInputType)
enabled = config.inputChannels [row * 2] || config.inputChannels [row * 2 + 1];
enabled = config.inputChannels[row * 2] || config.inputChannels[row * 2 + 1];
else if (type == audioOutputType)
enabled = config.outputChannels [row * 2] || config.outputChannels [row * 2 + 1];
enabled = config.outputChannels[row * 2] || config.outputChannels[row * 2 + 1];
}
else
{
if (type == audioInputType)
enabled = config.inputChannels [row];
enabled = config.inputChannels[row];
else if (type == audioOutputType)
enabled = config.outputChannels [row];
enabled = config.outputChannels[row];
}
const int x = getTickX();
const float tickW = height * 0.75f;
auto x = getTickX();
auto tickW = height * 0.75f;
getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW,
enabled, true, true, false);
@ -841,7 +822,7 @@ public:
{
ListBox::paint (g);
if (items.size() == 0)
if (items.isEmpty())
{
g.setColour (Colours::grey);
g.setFont (13.0f);
@ -881,7 +862,7 @@ public:
return name1.trim() + " + " + name2.substring (commonBit.length()).trim();
}
void flipEnablement (const int row)
void flipEnablement (int row)
{
jassert (type == audioInputType || type == audioOutputType);
@ -893,11 +874,11 @@ public:
if (setup.useStereoPairs)
{
BigInteger bits;
BigInteger& original = (type == audioInputType ? config.inputChannels
: config.outputChannels);
auto& original = (type == audioInputType ? config.inputChannels
: config.outputChannels);
for (int i = 0; i < 256; i += 2)
bits.setBit (i / 2, original [i] || original [i + 1]);
bits.setBit (i / 2, original[i] || original[i + 1]);
if (type == audioInputType)
{
@ -911,7 +892,7 @@ public:
}
for (int i = 0; i < 256; ++i)
original.setBit (i, bits [i / 2]);
original.setBit (i, bits[i / 2]);
}
else
{
@ -927,7 +908,7 @@ public:
}
}
String error (setup.manager->setAudioDeviceSetup (config, true));
auto error = setup.manager->setAudioDeviceSetup (config, true);
if (error.isNotEmpty())
{
@ -938,9 +919,9 @@ public:
static void flipBit (BigInteger& chans, int index, int minNumber, int maxNumber)
{
const int numActive = chans.countNumberOfSetBits();
auto numActive = chans.countNumberOfSetBits();
if (chans [index])
if (chans[index])
{
if (numActive > minNumber)
chans.setBit (index, false);
@ -949,11 +930,8 @@ public:
{
if (numActive >= maxNumber)
{
const int firstActiveChan = chans.findNextSetBit (0);
chans.setBit (index > firstActiveChan
? firstActiveChan : chans.getHighestBit(),
false);
auto firstActiveChan = chans.findNextSetBit (0);
chans.clearBit (index > firstActiveChan ? firstActiveChan : chans.getHighestBit());
}
chans.setBit (index, true);
@ -977,22 +955,22 @@ private:
//==============================================================================
AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager& dm,
const int minInputChannels_,
const int maxInputChannels_,
const int minOutputChannels_,
const int maxOutputChannels_,
const bool showMidiInputOptions,
const bool showMidiOutputSelector,
const bool showChannelsAsStereoPairs_,
const bool hideAdvancedOptionsWithButton_)
int minInputChannelsToUse,
int maxInputChannelsToUse,
int minOutputChannelsToUse,
int maxOutputChannelsToUse,
bool showMidiInputOptions,
bool showMidiOutputSelector,
bool showChannelsAsStereoPairsToUse,
bool hideAdvancedOptionsWithButtonToUse)
: deviceManager (dm),
itemHeight (24),
minOutputChannels (minOutputChannels_),
maxOutputChannels (maxOutputChannels_),
minInputChannels (minInputChannels_),
maxInputChannels (maxInputChannels_),
showChannelsAsStereoPairs (showChannelsAsStereoPairs_),
hideAdvancedOptionsWithButton (hideAdvancedOptionsWithButton_)
minOutputChannels (minOutputChannelsToUse),
maxOutputChannels (maxOutputChannelsToUse),
minInputChannels (minInputChannelsToUse),
maxInputChannels (maxInputChannelsToUse),
showChannelsAsStereoPairs (showChannelsAsStereoPairsToUse),
hideAdvancedOptionsWithButton (hideAdvancedOptionsWithButtonToUse)
{
jassert (minOutputChannels >= 0 && minOutputChannels <= maxOutputChannels);
jassert (minInputChannels >= 0 && minInputChannels <= maxInputChannels);
@ -1001,7 +979,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
if (types.size() > 1)
{
deviceTypeDropDown = new ComboBox (String());
deviceTypeDropDown = new ComboBox();
for (int i = 0; i < types.size(); ++i)
deviceTypeDropDown->addItem (types.getUnchecked(i)->getTypeName(), i + 1);
@ -1009,7 +987,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
addAndMakeVisible (deviceTypeDropDown);
deviceTypeDropDown->addListener (this);
deviceTypeDropDownLabel = new Label (String(), TRANS("Audio device type:"));
deviceTypeDropDownLabel = new Label ({}, TRANS("Audio device type:"));
deviceTypeDropDownLabel->setJustificationType (Justification::centredRight);
deviceTypeDropDownLabel->attachToComponent (deviceTypeDropDown, true);
}
@ -1020,7 +998,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
= new MidiInputSelectorComponentListBox (deviceManager,
"(" + TRANS("No MIDI inputs available") + ")"));
midiInputsLabel = new Label (String(), TRANS ("Active MIDI inputs:"));
midiInputsLabel = new Label ({}, TRANS ("Active MIDI inputs:"));
midiInputsLabel->setJustificationType (Justification::topRight);
midiInputsLabel->attachToComponent (midiInputsList, true);
@ -1028,7 +1006,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
{
addAndMakeVisible (bluetoothButton = new TextButton (TRANS("Bluetooth MIDI"),
TRANS("Scan for bluetooth MIDI devices")));
bluetoothButton->addListener (this);
bluetoothButton->onClick = [this]() { handleBluetoothButton(); };
}
}
else
@ -1040,7 +1018,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
if (showMidiOutputSelector)
{
addAndMakeVisible (midiOutputSelector = new ComboBox (String()));
addAndMakeVisible (midiOutputSelector = new ComboBox());
midiOutputSelector->addListener (this);
midiOutputLabel = new Label ("lm", TRANS("MIDI Output:"));
@ -1071,7 +1049,7 @@ void AudioDeviceSelectorComponent::setItemHeight (int newItemHeight)
void AudioDeviceSelectorComponent::resized()
{
Rectangle<int> r (proportionOfWidth (0.35f), 15, proportionOfWidth (0.6f), 3000);
const int space = itemHeight / 4;
auto space = itemHeight / 4;
if (deviceTypeDropDown != nullptr)
{
@ -1121,7 +1099,7 @@ void AudioDeviceSelectorComponent::comboBoxChanged (ComboBox* comboBoxThatHasCha
{
if (comboBoxThatHasChanged == deviceTypeDropDown)
{
if (AudioIODeviceType* const type = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown->getSelectedId() - 1])
if (auto* type = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown->getSelectedId() - 1])
{
audioDeviceSettingsComp.reset();
deviceManager.setCurrentAudioDeviceType (type->getTypeName(), true);
@ -1130,10 +1108,10 @@ void AudioDeviceSelectorComponent::comboBoxChanged (ComboBox* comboBoxThatHasCha
}
else if (comboBoxThatHasChanged == midiOutputSelector)
{
String midiDeviceName (midiOutputSelector->getText());
auto midiDeviceName = midiOutputSelector->getText();
if (midiDeviceName == getNoDeviceString())
midiDeviceName = String();
midiDeviceName = {};
deviceManager.setDefaultMidiOutput (midiDeviceName);
}
@ -1203,16 +1181,13 @@ void AudioDeviceSelectorComponent::updateAllControls()
resized();
}
void AudioDeviceSelectorComponent::buttonClicked (Button* btn)
void AudioDeviceSelectorComponent::handleBluetoothButton()
{
if (bluetoothButton == btn)
{
if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))
RuntimePermissions::request (RuntimePermissions::bluetoothMidi, nullptr);
if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))
RuntimePermissions::request (RuntimePermissions::bluetoothMidi, nullptr);
if (RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))
BluetoothMidiDevicePairingDialogue::open();
}
if (RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))
BluetoothMidiDevicePairingDialogue::open();
}
ListBox* AudioDeviceSelectorComponent::getMidiInputSelectorListBox() const noexcept

View file

@ -39,7 +39,6 @@ namespace juce
class JUCE_API AudioDeviceSelectorComponent : public Component,
private ChangeListener,
private ComboBox::Listener,
private Button::Listener,
private Timer
{
public:
@ -94,9 +93,6 @@ public:
void timerCallback() override;
private:
//==============================================================================
void buttonClicked (Button*) override;
//==============================================================================
ScopedPointer<ComboBox> deviceTypeDropDown;
ScopedPointer<Label> deviceTypeDropDownLabel;
@ -114,6 +110,7 @@ private:
ScopedPointer<Label> midiInputsLabel, midiOutputLabel;
ScopedPointer<TextButton> bluetoothButton;
void handleBluetoothButton();
void comboBoxChanged (ComboBox*) override;
void changeListenerCallback (ChangeBroadcaster*) override;
void updateAllControls();