| 
							- /*
 -   ==============================================================================
 - 
 -    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.
 - 
 -   ==============================================================================
 - */
 - 
 - #pragma once
 - 
 - #include "../JuceLibraryCode/JuceHeader.h"
 - #include "IAAEffectProcessor.h"
 - #include "SimpleMeter.h"
 - 
 - 
 - class IAAEffectEditor  : public AudioProcessorEditor,
 -                          private IAAEffectProcessor::MeterListener,
 -                          private Button::Listener,
 -                          private Timer
 - {
 - public:
 -     IAAEffectEditor (IAAEffectProcessor& p,
 -                      AudioProcessorValueTreeState& vts)
 -         : AudioProcessorEditor (p),
 -           processor (p),
 -           parameters (vts)
 -     {
 -         // Register for meter value updates.
 -         processor.addMeterListener (*this);
 - 
 -         gainSlider.setSliderStyle (Slider::SliderStyle::LinearVertical);
 -         gainSlider.setTextBoxStyle (Slider::TextEntryBoxPosition::TextBoxAbove, false, 60, 20);
 -         addAndMakeVisible (gainSlider);
 - 
 -         for (auto& meter : meters)
 -             addAndMakeVisible (meter);
 - 
 -         // Configure all the graphics for the transport control.
 - 
 -         transportText.setFont (Font (Font::getDefaultMonospacedFontName(), 18.0f, Font::plain));
 -         transportText.setJustificationType (Justification::topLeft);
 -         addChildComponent (transportText);
 - 
 -         Path rewindShape;
 -         rewindShape.addRectangle (0.0, 0.0, 5.0, buttonSize);
 -         rewindShape.addTriangle (0.0, buttonSize / 2, buttonSize, 0.0, buttonSize, buttonSize);
 -         rewindButton.setShape (rewindShape, true, true, false);
 -         rewindButton.addListener (this);
 -         addChildComponent (rewindButton);
 - 
 -         Path playShape;
 -         playShape.addTriangle (0.0, 0.0, 0.0, buttonSize, buttonSize, buttonSize / 2);
 -         playButton.setShape (playShape, true, true, false);
 -         playButton.addListener (this);
 -         addChildComponent (playButton);
 - 
 -         Path recordShape;
 -         recordShape.addEllipse (0.0, 0.0, buttonSize, buttonSize);
 -         recordButton.setShape (recordShape, true, true, false);
 -         recordButton.addListener (this);
 -         addChildComponent (recordButton);
 - 
 -         // Configure the switch to host button.
 - 
 -         switchToHostButtonLabel.setFont (Font (Font::getDefaultMonospacedFontName(), 18.0f, Font::plain));
 -         switchToHostButtonLabel.setJustificationType (Justification::centredRight);
 -         switchToHostButtonLabel.setText ("Switch to\nhost app:", dontSendNotification);
 -         addChildComponent (switchToHostButtonLabel);
 - 
 -         switchToHostButton.addListener (this);
 -         addChildComponent (switchToHostButton);
 - 
 -         Rectangle<int> screenSize = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
 -         setSize (screenSize.getWidth(), screenSize.getHeight());
 - 
 -         resized();
 - 
 -         startTimerHz (60);
 -     }
 - 
 -     ~IAAEffectEditor()
 -     {
 -         processor.removeMeterListener (*this);
 -     }
 - 
 -     //==============================================================================
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
 -     }
 - 
 -     void resized() override
 -     {
 -         auto area = getBounds().reduced (20);
 - 
 -         gainSlider.setBounds (area.removeFromLeft (60));
 - 
 -         for (auto& meter : meters)
 -         {
 -             area.removeFromLeft (10);
 -             meter.setBounds (area.removeFromLeft (20));
 -         }
 - 
 -         area.removeFromLeft (20);
 -         transportText.setBounds (area.removeFromTop (120));
 - 
 -         auto navigationArea = area.removeFromTop (buttonSize);
 -         rewindButton.setTopLeftPosition (navigationArea.getPosition());
 -         navigationArea.removeFromLeft (buttonSize + 10);
 -         playButton.setTopLeftPosition (navigationArea.getPosition());
 -         navigationArea.removeFromLeft (buttonSize + 10);
 -         recordButton.setTopLeftPosition (navigationArea.getPosition());
 - 
 -         area.removeFromTop (30);
 - 
 -         auto appSwitchArea = area.removeFromTop (buttonSize);
 -         switchToHostButtonLabel.setBounds (appSwitchArea.removeFromLeft (100));
 -         appSwitchArea.removeFromLeft (5);
 -         switchToHostButton.setBounds (appSwitchArea.removeFromLeft (buttonSize));
 -     }
 - 
 - private:
 -     //==============================================================================
 -     // Called from the audio thread.
 -     void handleNewMeterValue (int channel, float value) override
 -     {
 -         meters[(size_t) channel].update (value);
 -     }
 - 
 -     //==============================================================================
 -     void timerCallback () override
 -     {
 -         auto timeInfoSuccess = processor.updateCurrentTimeInfoFromHost (lastPosInfo);
 -         transportText.setVisible (timeInfoSuccess);
 - 
 -         if (timeInfoSuccess)
 -             updateTransportTextDisplay();
 - 
 -         updateTransportButtonsDisplay();
 - 
 -         updateSwitchToHostDisplay();
 -     }
 - 
 -     //==============================================================================
 -     void buttonClicked (Button* b) override
 -     {
 -         auto playHead = processor.getPlayHead();
 - 
 -         if (playHead != nullptr && playHead->canControlTransport())
 -         {
 -             if (b == &rewindButton)
 -             {
 -                 playHead->transportRewind();
 -             }
 -             else if (b == &playButton)
 -             {
 -                 playHead->transportPlay(! lastPosInfo.isPlaying);
 -             }
 -             else if (b == &recordButton)
 -             {
 -                 playHead->transportRecord (! lastPosInfo.isRecording);
 -             }
 -             else if (b == &switchToHostButton)
 -             {
 -                 PluginHostType hostType;
 - 
 -                 hostType.switchToHostApplication();
 -             }
 -         }
 -     }
 - 
 -     //==============================================================================
 -     // quick-and-dirty function to format a timecode string
 -     String timeToTimecodeString (double seconds)
 -     {
 -         auto millisecs = roundToInt (seconds * 1000.0);
 -         auto absMillisecs = std::abs (millisecs);
 - 
 -         return String::formatted ("%02d:%02d:%02d.%03d",
 -                                   millisecs / 360000,
 -                                   (absMillisecs / 60000) % 60,
 -                                   (absMillisecs / 1000) % 60,
 -                                   absMillisecs % 1000);
 -     }
 - 
 -     // A quick-and-dirty function to format a bars/beats string.
 -     String quarterNotePositionToBarsBeatsString (double quarterNotes, int numerator, int denominator)
 -     {
 -         if (numerator == 0 || denominator == 0)
 -             return "1|1|000";
 - 
 -         auto quarterNotesPerBar = (numerator * 4 / denominator);
 -         auto beats  = (fmod (quarterNotes, quarterNotesPerBar) / quarterNotesPerBar) * numerator;
 - 
 -         auto bar    = ((int) quarterNotes) / quarterNotesPerBar + 1;
 -         auto beat   = ((int) beats) + 1;
 -         auto ticks  = ((int) (fmod (beats, 1.0) * 960.0 + 0.5));
 - 
 -         return String::formatted ("%d|%d|%03d", bar, beat, ticks);
 -     }
 - 
 -     void updateTransportTextDisplay()
 -     {
 -         MemoryOutputStream displayText;
 - 
 -         displayText << "[" << SystemStats::getJUCEVersion() << "]\n"
 -                     << String (lastPosInfo.bpm, 2) << " bpm\n"
 -                     << lastPosInfo.timeSigNumerator << '/' << lastPosInfo.timeSigDenominator << "\n"
 -                     << timeToTimecodeString (lastPosInfo.timeInSeconds) << "\n"
 -                     << quarterNotePositionToBarsBeatsString (lastPosInfo.ppqPosition,
 -                                                  lastPosInfo.timeSigNumerator,
 -                                                  lastPosInfo.timeSigDenominator) << "\n";
 - 
 -         if (lastPosInfo.isRecording)
 -             displayText << "(recording)";
 -         else if (lastPosInfo.isPlaying)
 -             displayText << "(playing)";
 - 
 -         transportText.setText (displayText.toString(), dontSendNotification);
 -     }
 - 
 -     void updateTransportButtonsDisplay()
 -     {
 -         auto visible = processor.getPlayHead() != nullptr
 -                     && processor.getPlayHead()->canControlTransport();
 - 
 -         if (rewindButton.isVisible() != visible)
 -         {
 -             rewindButton.setVisible (visible);
 -             playButton.setVisible   (visible);
 -             recordButton.setVisible (visible);
 -         }
 - 
 -         if (visible)
 -         {
 -             Colour playColour = lastPosInfo.isPlaying ? Colours::green : defaultButtonColour;
 -             playButton.setColours (playColour, playColour, playColour);
 -             playButton.repaint();
 - 
 -             Colour recordColour = lastPosInfo.isRecording ? Colours::red : defaultButtonColour;
 -             recordButton.setColours (recordColour, recordColour, recordColour);
 -             recordButton.repaint();
 -         }
 -     }
 - 
 -     void updateSwitchToHostDisplay()
 -     {
 -         PluginHostType hostType;
 -         auto visible = hostType.isInterAppAudioConnected();
 - 
 -         if (switchToHostButtonLabel.isVisible() != visible)
 -         {
 -             switchToHostButtonLabel.setVisible (visible);
 -             switchToHostButton.setVisible (visible);
 - 
 -             if (visible)
 -             {
 -                 auto icon = hostType.getHostIcon (buttonSize);
 -                 switchToHostButton.setImages(false, true, true,
 -                                              icon, 1.0, Colours::transparentBlack,
 -                                              icon, 1.0, Colours::transparentBlack,
 -                                              icon, 1.0, Colours::transparentBlack);
 -             }
 -         }
 -     }
 - 
 -     IAAEffectProcessor& processor;
 -     AudioProcessorValueTreeState& parameters;
 - 
 -     const int buttonSize = 30;
 -     const Colour defaultButtonColour = Colours::darkgrey;
 -     ShapeButton rewindButton {"Rewind", defaultButtonColour, defaultButtonColour, defaultButtonColour};
 -     ShapeButton playButton   {"Play",   defaultButtonColour, defaultButtonColour, defaultButtonColour};
 -     ShapeButton recordButton {"Record", defaultButtonColour, defaultButtonColour, defaultButtonColour};
 - 
 -     Slider gainSlider;
 -     AudioProcessorValueTreeState::SliderAttachment gainAttachment = { parameters, "gain", gainSlider };
 - 
 -     std::array<SimpleMeter, 2> meters;
 - 
 -     ImageButton switchToHostButton;
 -     Label transportText, switchToHostButtonLabel;
 - 
 -     AudioPlayHead::CurrentPositionInfo lastPosInfo;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IAAEffectEditor)
 - };
 
 
  |