2 ==============================================================================
4 This file was auto-generated by the Jucer!
6 It contains the basic startup code for a Juce application.
8 ==============================================================================
11 #include "PluginProcessor.h"
12 #include "PluginEditor.h"
14 //==============================================================================
15 JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemoPluginAudioProcessor
* ownerFilter
)
16 : AudioProcessorEditor (ownerFilter
),
17 midiKeyboard (ownerFilter
->keyboardState
, MidiKeyboardComponent::horizontalKeyboard
),
18 infoLabel (String::empty
),
19 gainLabel ("", "Throughput level:"),
20 delayLabel ("", "Delay:"),
25 addAndMakeVisible (&gainSlider
);
26 gainSlider
.setSliderStyle (Slider::Rotary
);
27 gainSlider
.addListener (this);
28 gainSlider
.setRange (0.0, 1.0, 0.01);
30 addAndMakeVisible (&delaySlider
);
31 delaySlider
.setSliderStyle (Slider::Rotary
);
32 delaySlider
.addListener (this);
33 delaySlider
.setRange (0.0, 1.0, 0.01);
35 // add some labels for the sliders..
36 gainLabel
.attachToComponent (&gainSlider
, false);
37 gainLabel
.setFont (Font (11.0f
));
39 delayLabel
.attachToComponent (&delaySlider
, false);
40 delayLabel
.setFont (Font (11.0f
));
42 // add the midi keyboard component..
43 addAndMakeVisible (&midiKeyboard
);
45 // add a label that will display the current timecode and status..
46 addAndMakeVisible (&infoLabel
);
47 infoLabel
.setColour (Label::textColourId
, Colours::blue
);
49 // add the triangular resizer component for the bottom-right of the UI
50 addAndMakeVisible (resizer
= new ResizableCornerComponent (this, &resizeLimits
));
51 resizeLimits
.setSizeLimits (150, 150, 800, 300);
53 // set our component's initial size to be the last one that was stored in the filter's settings
54 setSize (ownerFilter
->lastUIWidth
,
55 ownerFilter
->lastUIHeight
);
60 JuceDemoPluginAudioProcessorEditor::~JuceDemoPluginAudioProcessorEditor()
64 //==============================================================================
65 void JuceDemoPluginAudioProcessorEditor::paint (Graphics
& g
)
67 g
.setGradientFill (ColourGradient (Colours::white
, 0, 0, Colours::grey
, 0, (float) getHeight(), false));
71 void JuceDemoPluginAudioProcessorEditor::resized()
73 infoLabel
.setBounds (10, 4, 400, 25);
74 gainSlider
.setBounds (20, 60, 150, 40);
75 delaySlider
.setBounds (200, 60, 150, 40);
77 const int keyboardHeight
= 70;
78 midiKeyboard
.setBounds (4, getHeight() - keyboardHeight
- 4, getWidth() - 8, keyboardHeight
);
80 resizer
->setBounds (getWidth() - 16, getHeight() - 16, 16, 16);
82 getProcessor()->lastUIWidth
= getWidth();
83 getProcessor()->lastUIHeight
= getHeight();
86 //==============================================================================
87 // This timer periodically checks whether any of the filter's parameters have changed...
88 void JuceDemoPluginAudioProcessorEditor::timerCallback()
90 JuceDemoPluginAudioProcessor
* ourProcessor
= getProcessor();
92 AudioPlayHead::CurrentPositionInfo
newPos (ourProcessor
->lastPosInfo
);
94 if (lastDisplayedPosition
!= newPos
)
95 displayPositionInfo (newPos
);
97 gainSlider
.setValue (ourProcessor
->gain
, false);
98 delaySlider
.setValue (ourProcessor
->delay
, false);
101 // This is our Slider::Listener callback, when the user drags a slider.
102 void JuceDemoPluginAudioProcessorEditor::sliderValueChanged (Slider
* slider
)
104 if (slider
== &gainSlider
)
106 // It's vital to use setParameterNotifyingHost to change any parameters that are automatable
107 // by the host, rather than just modifying them directly, otherwise the host won't know
108 // that they've changed.
109 getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::gainParam
,
110 (float) gainSlider
.getValue());
112 else if (slider
== &delaySlider
)
114 getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::delayParam
,
115 (float) delaySlider
.getValue());
119 //==============================================================================
120 // quick-and-dirty function to format a timecode string
121 static const String
timeToTimecodeString (const double seconds
)
123 const double absSecs
= fabs (seconds
);
125 const int hours
= (int) (absSecs
/ (60.0 * 60.0));
126 const int mins
= ((int) (absSecs
/ 60.0)) % 60;
127 const int secs
= ((int) absSecs
) % 60;
133 s
<< String (hours
).paddedLeft ('0', 2) << ":"
134 << String (mins
).paddedLeft ('0', 2) << ":"
135 << String (secs
).paddedLeft ('0', 2) << ":"
136 << String (roundToInt (absSecs
* 1000) % 1000).paddedLeft ('0', 3);
141 // quick-and-dirty function to format a bars/beats string
142 static const String
ppqToBarsBeatsString (double ppq
, double /*lastBarPPQ*/, int numerator
, int denominator
)
144 if (numerator
== 0 || denominator
== 0)
147 const int ppqPerBar
= (numerator
* 4 / denominator
);
148 const double beats
= (fmod (ppq
, ppqPerBar
) / ppqPerBar
) * numerator
;
150 const int bar
= ((int) ppq
) / ppqPerBar
+ 1;
151 const int beat
= ((int) beats
) + 1;
152 const int ticks
= ((int) (fmod (beats
, 1.0) * 960.0));
155 s
<< bar
<< '|' << beat
<< '|' << ticks
;
159 // Updates the text in our position label.
160 void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHead::CurrentPositionInfo
& pos
)
162 lastDisplayedPosition
= pos
;
164 displayText
.preallocateBytes (128);
166 displayText
<< String (pos
.bpm
, 2) << " bpm, "
167 << pos
.timeSigNumerator
<< '/' << pos
.timeSigDenominator
168 << " - " << timeToTimecodeString (pos
.timeInSeconds
)
169 << " - " << ppqToBarsBeatsString (pos
.ppqPosition
, pos
.ppqPositionOfLastBarStart
,
170 pos
.timeSigNumerator
, pos
.timeSigDenominator
);
173 displayText
<< " (recording)";
174 else if (pos
.isPlaying
)
175 displayText
<< " (playing)";
177 infoLabel
.setText (displayText
, false);