/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2017 - ROLI Ltd. JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 5 End-User License Agreement and JUCE 5 Privacy Policy (both updated and effective as of the 27th April 2017). End User License Agreement: www.juce.com/juce-5-licence Privacy Policy: www.juce.com/juce-5-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ class ChannelClickListener { public: virtual ~ChannelClickListener() {} virtual void channelButtonClicked (int channelIndex) = 0; virtual bool isChannelActive (int channelIndex) = 0; }; class SurroundEditor : public AudioProcessorEditor, public ButtonListener, private Timer { public: SurroundEditor (AudioProcessor& parent) : AudioProcessorEditor (parent), currentChannelLayout (AudioChannelSet::disabled()), noChannelsLabel ("noChannelsLabel", "Input disabled"), layoutTitle ("LayoutTitleLabel", getLayoutName()) { layoutTitle.setJustificationType (Justification::centred); addAndMakeVisible (layoutTitle); addAndMakeVisible (noChannelsLabel); setSize (640, 64); lastSuspended = ! getAudioProcessor()->isSuspended(); timerCallback(); startTimer (500); } ~SurroundEditor() { } void resized() override { Rectangle r = getLocalBounds(); layoutTitle.setBounds (r.removeFromBottom (16)); noChannelsLabel.setBounds (r); if (channelButtons.size() > 0) { const int buttonWidth = r.getWidth() / channelButtons.size(); for (int i = 0; i < channelButtons.size(); ++i) channelButtons[i]->setBounds (r.removeFromLeft (buttonWidth)); } } void paint (Graphics& g) override { g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId)); } void buttonClicked (Button* btn) override { if (TextButton* textButton = dynamic_cast (btn)) { const int channelIndex = channelButtons.indexOf (textButton); if (ChannelClickListener* listener = dynamic_cast (getAudioProcessor())) listener->channelButtonClicked (channelIndex); } } void updateGUI() { const AudioChannelSet& channelSet = getAudioProcessor()->getChannelLayoutOfBus (false, 0); if (channelSet != currentChannelLayout) { currentChannelLayout = channelSet; layoutTitle.setText (currentChannelLayout.getDescription(), NotificationType::dontSendNotification); channelButtons.clear(); activeChannels.resize (currentChannelLayout.size()); if (currentChannelLayout == AudioChannelSet::disabled()) { noChannelsLabel.setVisible (true); } else { const int numChannels = currentChannelLayout.size(); for (int i = 0; i < numChannels; ++i) { const String channelName = AudioChannelSet::getAbbreviatedChannelTypeName (currentChannelLayout.getTypeOfChannel (i)); TextButton* newButton; channelButtons.add (newButton = new TextButton (channelName, channelName)); newButton->addListener (this); addAndMakeVisible (newButton); } noChannelsLabel.setVisible (false); resized(); } if (ChannelClickListener* listener = dynamic_cast (getAudioProcessor())) { const auto activeColour = getLookAndFeel().findColour (Slider::thumbColourId); const auto inactiveColour = getLookAndFeel().findColour (Slider::trackColourId); for (int i = 0; i < activeChannels.size(); ++i) { bool isActive = listener->isChannelActive (i); activeChannels.getReference (i) = isActive; channelButtons [i]->setColour (TextButton::buttonColourId, isActive ? activeColour : inactiveColour); channelButtons [i]->repaint(); } } } } private: String getLayoutName() const { if (AudioProcessor* p = getAudioProcessor()) return p->getChannelLayoutOfBus (false, 0).getDescription(); return "Unknown"; } void timerCallback() override { if (getAudioProcessor()->isSuspended() != lastSuspended) { lastSuspended = getAudioProcessor()->isSuspended(); updateGUI(); } if (! lastSuspended) { if (ChannelClickListener* listener = dynamic_cast (getAudioProcessor())) { const auto activeColour = getLookAndFeel().findColour (Slider::thumbColourId); const auto inactiveColour = getLookAndFeel().findColour (Slider::trackColourId); for (int i = 0; i < activeChannels.size(); ++i) { bool isActive = listener->isChannelActive (i); if (activeChannels.getReference (i) != isActive) { activeChannels.getReference (i) = isActive; channelButtons [i]->setColour (TextButton::buttonColourId, isActive ? activeColour : inactiveColour); channelButtons [i]->repaint(); } } } } } AudioChannelSet currentChannelLayout; Label noChannelsLabel, layoutTitle; OwnedArray channelButtons; Array activeChannels; bool lastSuspended; };